﻿' LibWowArmory
' by Ronald M. Clifford (roncli@roncli.com)
'
' This source code is released under the GNU Library General Public License (LGPL) Version 2.1.

Imports Microsoft.VisualBasic
Imports roncliProductions
Imports roncliProductions.LibWowArmory
Imports roncliProductions.LibWowArmory.Achievement.Strings
Imports roncliProductions.LibWowArmory.Calendar.Detail
Imports roncliProductions.LibWowArmory.Calendar.Month
Imports roncliProductions.LibWowArmory.Calendar.Month.User
Imports roncliProductions.LibWowArmory.Calendar.Month.World
Imports roncliProductions.LibWowArmory.Character
Imports roncliProductions.LibWowArmory.Character.Achievements
Imports roncliProductions.LibWowArmory.Character.Achievements.Category
Imports roncliProductions.LibWowArmory.Character.Feed
Imports roncliProductions.LibWowArmory.Character.Reputation
Imports roncliProductions.LibWowArmory.Character.Search
Imports roncliProductions.LibWowArmory.Character.Sheet
Imports roncliProductions.LibWowArmory.Character.Statistics
Imports roncliProductions.LibWowArmory.Character.Statistics.Category
Imports roncliProductions.LibWowArmory.Character.Talents
Imports roncliProductions.LibWowArmory.Dungeon
Imports roncliProductions.LibWowArmory.Dungeon.Strings
Imports roncliProductions.LibWowArmory.Faction
Imports roncliProductions.LibWowArmory.Item.Info
Imports roncliProductions.LibWowArmory.Item.Search
Imports roncliProductions.LibWowArmory.Item.Tooltip
Imports roncliProductions.LibWowArmory.TalentTree
Imports System
Imports System.Collections.ObjectModel
Imports System.Globalization
Imports System.Linq

<Assembly: CLSCompliant(True)> 

Namespace roncliProductions.LibWowArmoryDemo

    Public Module modMain

        Public Sub Main()
            ' There are a number of things to test here, so we will give the user the option of which test to perform.
            Do
                Console.WriteLine("Please choose a test to perform")
                Console.WriteLine("  Or press enter to quit.")
                Console.WriteLine("1 - Achievement Strings")
                Console.WriteLine("2 - Calendar")
                Console.WriteLine("3 - Character Achievements")
                Console.WriteLine("4 - Character Feed")
                Console.WriteLine("5 - Character Reputation")
                Console.WriteLine("6 - Character Search")
                Console.WriteLine("7 - Character Sheet")
                Console.WriteLine("8 - Character Statistics")
                Console.WriteLine("9 - Character Talents")
                Console.WriteLine("10 - Dungeons")
                Console.WriteLine("11 - Factions")
                Console.WriteLine("12 - Item Info")
                Console.WriteLine("13 - Item Search")
                Console.WriteLine("14 - Item Tooltip")
                Console.Write(">")
                Dim strResponse As String = Console.ReadLine
                If String.IsNullOrEmpty(strResponse) Then Exit Do
                Dim intResponse As Integer
                If Integer.TryParse(strResponse, intResponse) Then
                    Select Case intResponse
                        Case 1
                            AchievementStringsDemo()
                        Case 2
                            CalendarDemo()
                        Case 3
                            CharacterAchievementsDemo()
                        Case 4
                            CharacterFeedDemo()
                        Case 5
                            CharacterReputationDemo()
                        Case 6
                            CharacterSearchDemo()
                        Case 7
                            CharacterSheetDemo()
                        Case 8
                            CharacterStatisticsDemo()
                        Case 9
                            CharacterTalentsDemo()
                        Case 10
                            DungeonDemo()
                        Case 11
                            FactionsDemo()
                        Case 12
                            ItemInfoDemo()
                        Case 13
                            ItemSearchDemo()
                        Case 14
                            ItemTooltipDemo()
                    End Select
                    Console.Clear()
                Else
                    Console.WriteLine("Invalid response.")
                    Console.WriteLine()
                End If
            Loop
        End Sub

        Private Sub AchievementStringsDemo()
            Console.Clear()
            Console.WriteLine("Achievement Strings Demo")
            Console.WriteLine()

            ' Get the achievement strings from the Armory
            Dim asStrings As New AchievementStrings()

            ' Print out the achievement categories
            Console.WriteLine("Achievement Categories")
            For Each cCategory As LibWowArmory.Achievement.Strings.CategoryInfo In asStrings.Categories
                Console.WriteLine("{0} - {1}", cCategory.CategoryID, cCategory.Name)
                For Each sSubcategory As LibWowArmory.Achievement.Strings.SubcategoryInfo In cCategory.Subcategories
                    Console.WriteLine("  {0}", sSubcategory.Name)
                Next
            Next
            Console.WriteLine()

            ' Print out the achievements
            Console.WriteLine("Achievements")
            For Each aAchievement As LibWowArmory.Achievement.Strings.Achievement In asStrings.Achievements
                If String.IsNullOrEmpty(aAchievement.Reward) Then
                    Console.WriteLine("{0} - {1} - {2}", aAchievement.AchievementID, aAchievement.Title, aAchievement.Desc)
                Else
                    Console.WriteLine("{0} - {1} - {2} - {3}", aAchievement.AchievementID, aAchievement.Title, aAchievement.Desc, aAchievement.Reward)
                End If
            Next
            Console.WriteLine()

            Console.WriteLine("Press any key to continue.")
            Console.ReadKey(True)
        End Sub

        Private Sub CalendarDemo()
            Console.Clear()
            Console.WriteLine("Calendar Demo")
            Console.WriteLine()

            ' Declare some variables
            Dim strUsername As String
            Dim strPassword As String = String.Empty
            Dim strCharacter As String
            Dim strRealm As String

            ' First, get the username
            Do
                Console.WriteLine("Please enter your World of Warcraft/Battle.Net account user name.")
                Console.Write(">")
                strUsername = Console.ReadLine

                If String.IsNullOrEmpty(strUsername) Then
                    Console.WriteLine("You must enter a username.")
                    Console.WriteLine()
                Else
                    Exit Do
                End If
            Loop

            ' Next, get the password
            Do
                Console.WriteLine("Please enter your password.")
                Console.Write(">")
                Do
                    Dim ckiKey As ConsoleKeyInfo = Console.ReadKey(True)
                    If ckiKey.Key = ConsoleKey.Enter Then Exit Do
                    strPassword = String.Format(CultureInfo.InvariantCulture, "{0}{1}", strPassword, ckiKey.KeyChar)
                Loop
                Console.WriteLine()
                If String.IsNullOrEmpty(strPassword) Then
                    Console.WriteLine("You must enter a password.")
                    Console.WriteLine()
                Else
                    Exit Do
                End If
            Loop

            ' Next, get the character
            Do
                Console.WriteLine("Please enter the name of the character whose calendar you wish to retrieve.")
                Console.Write(">")
                strCharacter = Console.ReadLine

                If String.IsNullOrEmpty(strCharacter) Then
                    Console.WriteLine("You must enter a character name.")
                    Console.WriteLine()
                Else
                    Exit Do
                End If
            Loop

            ' Next, get the realm
            Do
                Console.WriteLine("Please enter the name of the character's realm.")
                Console.Write(">")
                strRealm = Console.ReadLine

                If String.IsNullOrEmpty(strRealm) Then
                    Console.WriteLine("You must enter a realm.")
                    Console.WriteLine()
                Else
                    Exit Do
                End If
            Loop

            ' Get the events for this month
            Dim cmwBattlegrounds As New CalendarMonthWorld(strUsername, strPassword, strRealm, strCharacter, Date.Now, Enums.CalendarType.BattlegroundHolidays)
            Dim cmwDarkmoon As New CalendarMonthWorld(strUsername, strPassword, strRealm, strCharacter, Date.Now, Enums.CalendarType.DarkmoonFaire)
            Dim cmwRaidLockouts As New CalendarMonthWorld(strUsername, strPassword, strRealm, strCharacter, Date.Now, Enums.CalendarType.RaidLockouts)
            Dim cmwRaidResets As New CalendarMonthWorld(strUsername, strPassword, strRealm, strCharacter, Date.Now, Enums.CalendarType.RaidResets)
            Dim cmwWeeklyHolidays As New CalendarMonthWorld(strUsername, strPassword, strRealm, strCharacter, Date.Now, Enums.CalendarType.WeeklyHolidays)
            Dim cmwWorldHolidays As New CalendarMonthWorld(strUsername, strPassword, strRealm, strCharacter, Date.Now, Enums.CalendarType.WorldHolidays)
            Dim cmuCalendar As New CalendarMonthUser(strUsername, strPassword, strRealm, strCharacter, Date.Now)


            Do
                ' Show the calendar for this month
                Console.Clear()
                Console.WriteLine("Events for {0}-{1} for the month of {2:MMMM, yyyy}", strRealm, strCharacter, cmuCalendar.Month)
                Console.WriteLine("Calendar Type: {0}", cmuCalendar.CalendarType)
                Console.WriteLine("Timezone Offset: {0}", cmuCalendar.TimezoneOffset)
                Console.WriteLine()

                ' List this month's events
                Console.WriteLine("Battleground Holidays")
                For Each eEvent As World.CalendarEvent In cmwBattlegrounds.Events.OrderBy(Function(e) e.Start)
                    Console.WriteLine("{0}-{1} - {2}", eEvent.Start, eEvent.End, eEvent.Summary)
                Next
                Console.WriteLine()

                Console.WriteLine("Darkmoon Faire")
                For Each eEvent As World.CalendarEvent In cmwDarkmoon.Events.OrderBy(Function(e) e.Start)
                    Console.WriteLine("{0}-{1} - {2}", eEvent.Start, eEvent.End, eEvent.Summary)
                Next
                Console.WriteLine()

                Console.WriteLine("Raid Lockouts")
                For Each eEvent As World.CalendarEvent In cmwRaidLockouts.Events.OrderBy(Function(e) e.Start)
                    Console.WriteLine("{0}-{1} - {2}", eEvent.Start, eEvent.End, eEvent.Summary)
                Next
                Console.WriteLine()

                Console.WriteLine("Raid Resets")
                For Each eEvent As World.CalendarEvent In cmwRaidResets.Events.OrderBy(Function(e) e.Start)
                    Console.WriteLine("{0}-{1} - {2}", eEvent.Start, eEvent.End, eEvent.Summary)
                Next
                Console.WriteLine()

                Console.WriteLine("Weekly Holidays")
                For Each eEvent As World.CalendarEvent In cmwWeeklyHolidays.Events.OrderBy(Function(e) e.Start)
                    Console.WriteLine("{0}-{1} - {2}", eEvent.Start, eEvent.End, eEvent.Summary)
                Next
                Console.WriteLine()

                Console.WriteLine("World Holidays")
                For Each eEvent As World.CalendarEvent In cmwWorldHolidays.Events.OrderBy(Function(e) e.Start)
                    Console.WriteLine("{0}-{1} - {2}", eEvent.Start, eEvent.End, eEvent.Summary)
                Next
                Console.WriteLine()

                Console.WriteLine("Player Events")
                For Each eEvent As User.CalendarEvent In cmuCalendar.Events.OrderBy(Function(e) e.Start)
                    Console.WriteLine("{0} - {1} - {2} - {3}", eEvent.EventID, eEvent.Start, eEvent.EventType, eEvent.Summary)
                Next
                Console.WriteLine()

                Do
                    ' Prompt to show event detail, change months, or exit
                    Console.WriteLine("Enter the event ID to show the detail for that event")
                    Console.WriteLine("  or enter NEXT for next month")
                    Console.WriteLine("  or enter PREV for previous month")
                    Console.WriteLine("  or press enter to quit")
                    Console.Write(">")
                    Dim strResponse As String = Console.ReadLine
                    Dim intResponse As Integer
                    If Integer.TryParse(strResponse, intResponse) Then
                        CalendarDetail(strUsername, strPassword, strRealm, strCharacter, intResponse)
                        Exit Do
                    Else
                        If String.IsNullOrEmpty(strResponse) Then
                            Exit Sub
                        End If
                        Select Case strResponse.ToUpperInvariant
                            Case "NEXT"
                                cmwBattlegrounds = New CalendarMonthWorld(strUsername, strPassword, strRealm, strCharacter, cmwBattlegrounds.Month.AddMonths(1), Enums.CalendarType.BattlegroundHolidays)
                                cmwDarkmoon = New CalendarMonthWorld(strUsername, strPassword, strRealm, strCharacter, cmwDarkmoon.Month.AddMonths(1), Enums.CalendarType.DarkmoonFaire)
                                cmwRaidLockouts = New CalendarMonthWorld(strUsername, strPassword, strRealm, strCharacter, cmwRaidLockouts.Month.AddMonths(1), Enums.CalendarType.RaidLockouts)
                                cmwRaidResets = New CalendarMonthWorld(strUsername, strPassword, strRealm, strCharacter, cmwRaidResets.Month.AddMonths(1), Enums.CalendarType.RaidResets)
                                cmwWeeklyHolidays = New CalendarMonthWorld(strUsername, strPassword, strRealm, strCharacter, cmwWeeklyHolidays.Month.AddMonths(1), Enums.CalendarType.WeeklyHolidays)
                                cmwWorldHolidays = New CalendarMonthWorld(strUsername, strPassword, strRealm, strCharacter, cmwWorldHolidays.Month.AddMonths(1), Enums.CalendarType.WorldHolidays)
                                cmuCalendar = New CalendarMonthUser(strUsername, strPassword, strRealm, strCharacter, cmuCalendar.Month.AddMonths(1))
                                Exit Do
                            Case "PREV"
                                cmwBattlegrounds = New CalendarMonthWorld(strUsername, strPassword, strRealm, strCharacter, cmwBattlegrounds.Month.AddMonths(-1), Enums.CalendarType.BattlegroundHolidays)
                                cmwDarkmoon = New CalendarMonthWorld(strUsername, strPassword, strRealm, strCharacter, cmwDarkmoon.Month.AddMonths(-1), Enums.CalendarType.DarkmoonFaire)
                                cmwRaidLockouts = New CalendarMonthWorld(strUsername, strPassword, strRealm, strCharacter, cmwRaidLockouts.Month.AddMonths(-1), Enums.CalendarType.RaidLockouts)
                                cmwRaidResets = New CalendarMonthWorld(strUsername, strPassword, strRealm, strCharacter, cmwRaidResets.Month.AddMonths(-1), Enums.CalendarType.RaidResets)
                                cmwWeeklyHolidays = New CalendarMonthWorld(strUsername, strPassword, strRealm, strCharacter, cmwWeeklyHolidays.Month.AddMonths(-1), Enums.CalendarType.WeeklyHolidays)
                                cmwWorldHolidays = New CalendarMonthWorld(strUsername, strPassword, strRealm, strCharacter, cmwWorldHolidays.Month.AddMonths(-1), Enums.CalendarType.WorldHolidays)
                                cmuCalendar = New CalendarMonthUser(strUsername, strPassword, strRealm, strCharacter, cmuCalendar.Month.AddMonths(-1))
                                Exit Do
                            Case Else
                                Console.WriteLine("Invalid response.")
                                Console.WriteLine()
                        End Select
                    End If
                Loop
            Loop
        End Sub

        Private Sub CalendarDetail(ByVal strUsername As String, ByVal strPassword As String, ByVal strRealm As String, ByVal strCharacter As String, ByVal intEventID As Integer)
            ' Get event detail
            Dim cdCalendar As New CalendarDetail(strUsername, strPassword, strRealm, strCharacter, intEventID)

            ' Disply event detail
            Console.Clear()
            Console.WriteLine("{0} - {1}", cdCalendar.Start, cdCalendar.Summary)
            Console.WriteLine()
            Console.WriteLine("Type: {0}", cdCalendar.EventType)
            Console.WriteLine("Location: {0}", cdCalendar.Location)
            Console.WriteLine("Owner: {0}", cdCalendar.Owner)
            Console.WriteLine("Timezone Offset: {0}", cdCalendar.TimezoneOffset)
            Console.WriteLine()
            Console.WriteLine(cdCalendar.Description)
            Console.WriteLine()
            For Each iInvitee As Invitee In cdCalendar.Invitees.OrderBy(Function(i) i.Invitee)
                Console.WriteLine("{0} - {1} {2} - {3}", iInvitee.Invitee, [Enum].GetName(GetType(Enums.RaceType), iInvitee.Race), [Enum].GetName(GetType(Enums.ClassType), iInvitee.Class), iInvitee.Status)
            Next
            Console.WriteLine()

            Console.WriteLine("Press any key to continue.")
            Console.ReadKey(True)
        End Sub

        Private Sub CharacterAchievementsDemo()
            Console.Clear()
            Console.WriteLine("Character Achievements Demo")
            Console.WriteLine()

            Dim strCharacter As String
            Dim strRealm As String

            ' First, get the character
            Do
                Console.WriteLine("Please enter the name of the character whose achievements you wish to retrieve.")
                Console.Write(">")
                strCharacter = Console.ReadLine

                If String.IsNullOrEmpty(strCharacter) Then
                    Console.WriteLine("You must enter a character name.")
                    Console.WriteLine()
                Else
                    Exit Do
                End If
            Loop

            ' Next, get the realm
            Do
                Console.WriteLine("Please enter the name of the character's realm.")
                Console.Write(">")
                strRealm = Console.ReadLine

                If String.IsNullOrEmpty(strRealm) Then
                    Console.WriteLine("You must enter a realm.")
                    Console.WriteLine()
                Else
                    Exit Do
                End If
            Loop

            Dim caAchievements As New CharacterAchievements(strRealm, strCharacter)

            ' Display the achievements
            Do
                Console.Clear()
                Console.WriteLine("Achievements for {0}-{1}", strRealm, strCharacter)
                Console.WriteLine("{0}/{1} achievements earned - {2} points/{3}", caAchievements.AchievementsEarned, caAchievements.AchievementsTotal, caAchievements.AchievementPointsEarned, caAchievements.AchievementPointsTotal)

                If caAchievements.RecentAchievements.Count > 0 Then
                    Console.WriteLine()
                    Console.WriteLine("Most recent achievements:")
                    For Each aAchievement As LibWowArmory.Character.Achievements.Achievement In caAchievements.RecentAchievements
                        Console.WriteLine("{0} - {1} - {2}", aAchievement.DateCompleted, aAchievement.Title, aAchievement.Desc)
                    Next
                End If

                Console.WriteLine()
                Console.WriteLine("Select a category")
                Console.WriteLine("  or press enter to exit")
                For Each cCategory As LibWowArmory.Character.Achievements.CategoryInfo In caAchievements.Categories
                    If cCategory.TotalPoints = 0 Then
                        Console.WriteLine("{0}) {1}", caAchievements.Categories.IndexOf(cCategory), cCategory.Name)
                    Else
                        Console.WriteLine("{0}) {1} - {2}/{3} - {4} points/{5}", caAchievements.Categories.IndexOf(cCategory), cCategory.Name, cCategory.Earned, cCategory.Total, cCategory.EarnedPoints, cCategory.TotalPoints)
                    End If
                Next

                Console.Write(">")
                Dim strResponse As String = Console.ReadLine
                If String.IsNullOrEmpty(strResponse) Then Exit Do
                Dim intResponse As Integer
                If Integer.TryParse(strResponse, intResponse) Then
                    If intResponse >= 0 And intResponse < caAchievements.Categories.Count Then
                        Console.Clear()
                        AchievementCategoryDetail(caAchievements.Categories(intResponse), caAchievements.CategoryAchievements(caAchievements.Categories(intResponse)).Achievements)
                        Console.WriteLine()
                        Console.WriteLine("Press any key to continue.")
                        Console.ReadKey(True)
                    End If
                End If
            Loop
        End Sub

        Private Sub AchievementCategoryDetail(ByRef cCategory As LibWowArmory.Character.Achievements.CategoryInfo, ByRef cacCategory As LibWowArmory.Character.Achievements.Category.Category)
            Console.WriteLine("{0} achievements", cCategory.Name)
            Console.WriteLine()
            For Each aAchievement As LibWowArmory.Character.Achievements.Achievement In cacCategory.Achievements
                AchievementDetail(aAchievement)
                Console.WriteLine()
            Next
            For Each cSubcategory As LibWowArmory.Character.Achievements.Category.Category In cacCategory.Subcategories
                AchievementSubcategoryDetail(cCategory.Subcategories(cacCategory.Subcategories.IndexOf(cSubcategory)), cSubcategory)
            Next
        End Sub

        Private Sub AchievementSubcategoryDetail(ByRef sCategory As LibWowArmory.Character.Achievements.SubcategoryInfo, ByRef cacCategory As LibWowArmory.Character.Achievements.Category.Category)
            Console.WriteLine("{0} achievements", sCategory.Name)
            Console.WriteLine()
            For Each aAchievement As LibWowArmory.Character.Achievements.Achievement In cacCategory.Achievements
                AchievementDetail(aAchievement)
                Console.WriteLine()
            Next
        End Sub

        Private Sub AchievementDetail(ByRef aAchievement As LibWowArmory.Character.Achievements.Achievement)
            Console.WriteLine("{0} - {1}", aAchievement.Title, aAchievement.Desc)
            If aAchievement.DateCompleted <> Date.MinValue Then
                If aAchievement.Points > 0 Then
                    Console.WriteLine("Completed {0} - {1} points", aAchievement.DateCompleted, aAchievement.Points)
                Else
                    Console.WriteLine("Completed {0}", aAchievement.DateCompleted)
                End If
            Else
                If aAchievement.Points > 0 Then
                    Console.WriteLine("{0} points", aAchievement.Points)
                End If
            End If
            If Not String.IsNullOrEmpty(aAchievement.Reward) Then
                Console.WriteLine("Rewards {0}", aAchievement.Reward)
            End If
            For Each cCriteria As AchievementCriteria In aAchievement.AchievementCriteria
                If Not String.IsNullOrEmpty(cCriteria.Name) Then
                    Console.Write("- {0} ", cCriteria.Name)
                End If
                If aAchievement.DateCompleted = Date.MinValue And cCriteria.Date <> Date.MinValue Then
                    Console.Write("- Completed {0} ", cCriteria.Date)
                End If
                If aAchievement.DateCompleted = Date.MinValue Then
                    If cCriteria.MaxQuantity > 0 Then
                        Console.Write("- {0}/{1} ", cCriteria.Quantity, cCriteria.MaxQuantity)
                    End If
                    If cCriteria.MaxQuantityCurrency > 0 Then
                        Console.Write("- {0}g {1}s {2}c/{3}g {4}s {5}c ", Math.Floor(cCriteria.QuantityCurrency / 10000), Math.Floor(cCriteria.QuantityCurrency / 100) Mod 100, cCriteria.QuantityCurrency Mod 100, Math.Floor(cCriteria.MaxQuantityCurrency / 10000), Math.Floor(cCriteria.MaxQuantityCurrency / 100) Mod 100, cCriteria.MaxQuantityCurrency Mod 100)
                    End If
                Else
                    If cCriteria.MaxQuantity > 0 Then
                        Console.Write("- {0}/{0} ", cCriteria.MaxQuantity)
                    End If
                    If cCriteria.MaxQuantityCurrency > 0 Then
                        Console.Write("- {0}g {1}s {2}c/{0}g {1}s {2}c ", Math.Floor(cCriteria.MaxQuantityCurrency / 10000), Math.Floor(cCriteria.MaxQuantityCurrency / 100) Mod 100, cCriteria.MaxQuantityCurrency Mod 100)
                    End If
                End If
                Console.WriteLine()
            Next
            If aAchievement.PreviousAchievements.Count > 0 Then
                Console.WriteLine("Previous achievements in this series:")
                For Each aPreviousAchievement As LibWowArmory.Character.Achievements.Achievement In aAchievement.PreviousAchievements
                    AchievementDetail(aPreviousAchievement)
                Next
            End If
        End Sub

        Private Sub CharacterFeedDemo()
            Console.Clear()
            Console.WriteLine("Character Feed Demo")
            Console.WriteLine()

            Dim strCharacter As String
            Dim strRealm As String

            ' First, get the character
            Do
                Console.WriteLine("Please enter the name of the character whose reputation you wish to retrieve.")
                Console.Write(">")
                strCharacter = Console.ReadLine

                If String.IsNullOrEmpty(strCharacter) Then
                    Console.WriteLine("You must enter a character name.")
                    Console.WriteLine()
                Else
                    Exit Do
                End If
            Loop

            ' Next, get the realm
            Do
                Console.WriteLine("Please enter the name of the character's realm.")
                Console.Write(">")
                strRealm = Console.ReadLine

                If String.IsNullOrEmpty(strRealm) Then
                    Console.WriteLine("You must enter a realm.")
                    Console.WriteLine()
                Else
                    Exit Do
                End If
            Loop

            ' Now load up the options
            Dim cfFeed As New CharacterFeed(strCharacter, strRealm)

            ' Pick the main filters
            Do
                Console.Clear()
                Console.WriteLine("Please select the options you would like to filter for.")
                Console.WriteLine("  Or press enter to continue.")
                Console.WriteLine("1 - Achievements - {0}", If(cfFeed.Achievements, "Yes", "No"))
                Console.WriteLine("2 - Achievement Criteria - {0}", If(cfFeed.AchievementCriteria, "Yes", "No"))
                Console.WriteLine("3 - Boss Kills - {0}", If(cfFeed.BossKills, "Yes", "No"))
                Console.WriteLine("4 - Loot Received - {0}", If(cfFeed.Loot, "Yes", "No"))
                Console.WriteLine("5 - Talent Respecs - {0}", If(cfFeed.Respecs, "Yes", "No"))

                Console.Write(">")
                Dim strResponse As String = Console.ReadLine
                If String.IsNullOrEmpty(strResponse) Then Exit Do
                Dim intResponse As Integer
                If Integer.TryParse(strResponse, intResponse) Then
                    If intResponse >= 1 And intResponse <= 5 Then
                        Select Case intResponse
                            Case 1
                                cfFeed.Achievements = Not cfFeed.Achievements
                            Case 2
                                cfFeed.AchievementCriteria = Not cfFeed.AchievementCriteria
                            Case 3
                                cfFeed.BossKills = Not cfFeed.BossKills
                            Case 4
                                cfFeed.Loot = Not cfFeed.Loot
                            Case 5
                                cfFeed.Respecs = Not cfFeed.Respecs
                        End Select
                    End If
                End If
            Loop

            ' Now pick the achievement categories if applicable
            If cfFeed.Achievements Then
                Do
                    Console.Clear()
                    Console.WriteLine("Please select the achievement categories you would like to filter for.")
                    Console.WriteLine("  Or press enter to continue.")
                    For Each cCategory As AchievementCategory In cfFeed.Categories
                        Console.WriteLine("{0} - {1} - {2}", cCategory.CategoryID, cCategory.Name, If(cCategory.Include, "Yes", "No"))
                    Next

                    Console.Write(">")
                    Dim strResponse As String = Console.ReadLine
                    If String.IsNullOrEmpty(strResponse) Then Exit Do
                    Dim intResponse As Integer
                    If Integer.TryParse(strResponse, intResponse) Then
                        Dim varCategory = (cfFeed.Categories.Where(Function(c) c.CategoryID = intResponse))
                        If varCategory.Count > 0 Then
                            varCategory.First.Include = Not varCategory.First.Include
                        End If
                    End If
                Loop
            End If

            ' Finally, display the results
            cfFeed.Load()

            Console.Clear()
            Console.WriteLine("Character Feed for {0}-{1}", strRealm, strCharacter)
            Console.WriteLine()
            For Each feEvent As FeedEvent In cfFeed.Feed
                Console.WriteLine("{0} - {1}", feEvent.EventDate, feEvent.EventType)
                Console.WriteLine("  {0}", feEvent.Title)
                Console.WriteLine("  {0}", feEvent.Description)
                Console.WriteLine()
            Next

            Console.WriteLine()
            Console.WriteLine("Press any key to continue.")
            Console.ReadKey(True)
        End Sub

        Private Sub CharacterReputationDemo()
            Console.Clear()
            Console.WriteLine("Character Reputation Demo")
            Console.WriteLine()

            Dim strCharacter As String
            Dim strRealm As String

            ' First, get the character
            Do
                Console.WriteLine("Please enter the name of the character whose reputation you wish to retrieve.")
                Console.Write(">")
                strCharacter = Console.ReadLine

                If String.IsNullOrEmpty(strCharacter) Then
                    Console.WriteLine("You must enter a character name.")
                    Console.WriteLine()
                Else
                    Exit Do
                End If
            Loop

            ' Next, get the realm
            Do
                Console.WriteLine("Please enter the name of the character's realm.")
                Console.Write(">")
                strRealm = Console.ReadLine

                If String.IsNullOrEmpty(strRealm) Then
                    Console.WriteLine("You must enter a realm.")
                    Console.WriteLine()
                Else
                    Exit Do
                End If
            Loop

            Dim crReputation As New CharacterReputation(strRealm, strCharacter)

            ' Disply reputation
            Console.Clear()
            Console.WriteLine("Reputations for {0}-{1}", strRealm, strCharacter)
            Console.WriteLine()
            For Each rReputation As Reputation In crReputation.Reputation
                ListReputations(rReputation, 0)
            Next

            Console.WriteLine()
            Console.WriteLine("Press any key to continue.")
            Console.ReadKey(True)
        End Sub

        Private Sub ListReputations(ByVal rReputation As Reputation, ByVal intParents As Integer)
            If rReputation.Status = "None" Then
                Console.WriteLine("{0}{1}", StrDup(intParents, "  "), rReputation.Name)
            Else
                Console.WriteLine("{0}{1} - {2}/{3} {4}", StrDup(intParents, "  "), rReputation.Name, rReputation.Reputation, rReputation.MaxReputation, rReputation.Status)
            End If

            If rReputation.Reputations IsNot Nothing Then
                For Each rChildReputation As Reputation In rReputation.Reputations
                    ListReputations(rChildReputation, intParents + 1)
                Next
            End If
        End Sub

        Private Sub CharacterSearchDemo()
            Console.Clear()
            Console.WriteLine("Character Search Demo")
            Console.WriteLine()

            Dim strCharacter As String

            ' Get the search text
            Do
                Console.WriteLine("Please enter the text you wish to search for.")
                Console.Write(">")
                strCharacter = Console.ReadLine

                If String.IsNullOrEmpty(strCharacter) Then
                    Console.WriteLine("You must enter some search text.")
                    Console.WriteLine()
                Else
                    Exit Do
                End If
            Loop

            ' Do the search
            Dim csSearch As New CharacterSearch(strCharacter)

            ' Display the results
            Console.Clear()
            Console.WriteLine("Character Search Results for {0}", strCharacter)
            Console.WriteLine()
            If csSearch.Characters Is Nothing Then
                Console.WriteLine("No Results")
            ElseIf csSearch.Characters.Count = 0 Then
                Console.WriteLine("No Results")
            Else
                For Each cCharacter As Character In csSearch.Characters
                    Console.WriteLine("{0} - {1} - {2} - {3} - {4} {5}", cCharacter.Name, cCharacter.Realm, cCharacter.Level, cCharacter.Guild, [Enum].GetName(GetType(Enums.RaceType), cCharacter.Race), [Enum].GetName(GetType(Enums.ClassType), cCharacter.Class))
                Next
            End If

            Console.WriteLine()
            Console.WriteLine("Press any key to continue.")
            Console.ReadKey(True)
        End Sub

        Private Sub CharacterSheetDemo()
            Console.Clear()
            Console.WriteLine("Character Sheet Demo")
            Console.WriteLine()

            Dim strCharacter As String
            Dim strRealm As String

            ' First, get the character
            Do
                Console.WriteLine("Please enter the name of the character you wish to retrieve.")
                Console.Write(">")
                strCharacter = Console.ReadLine

                If String.IsNullOrEmpty(strCharacter) Then
                    Console.WriteLine("You must enter a character name.")
                    Console.WriteLine()
                Else
                    Exit Do
                End If
            Loop

            ' Next, get the realm
            Do
                Console.WriteLine("Please enter the name of the character's realm.")
                Console.Write(">")
                strRealm = Console.ReadLine

                If String.IsNullOrEmpty(strRealm) Then
                    Console.WriteLine("You must enter a realm.")
                    Console.WriteLine()
                Else
                    Exit Do
                End If
            Loop

            ' Do the lookup
            Dim csSheet As New CharacterSheet(strRealm, strCharacter)

            ' Display the results
            Console.Clear()
            Console.WriteLine("Character Sheet for {0}-{1}", strRealm, strCharacter)
            Console.WriteLine("Last Updated {0}", csSheet.LastModified)
            Console.WriteLine()

            Console.WriteLine("{0}{1}{2} - {3} - Level {4} {5} {6} {7}", csSheet.Prefix, csSheet.Name, csSheet.Suffix, csSheet.GuildName, csSheet.Level, [Enum].GetName(GetType(Enums.GenderType), csSheet.Gender), [Enum].GetName(GetType(Enums.RaceType), csSheet.Race), [Enum].GetName(GetType(Enums.ClassType), csSheet.Class))
            Console.WriteLine("Realm {0} - Battlegroup {1}", csSheet.Realm, csSheet.BattleGroup)
            Console.WriteLine()

            Console.WriteLine("Main Spec: {0} {1}/{2}/{3}", csSheet.PrimaryTalentSpec, csSheet.PrimaryTalentPoints(1), csSheet.PrimaryTalentPoints(2), csSheet.PrimaryTalentPoints(3))
            If csSheet.SecondaryTalentSpec <> "n/a" Then
                Console.WriteLine("Dual Spec: {0} {1}/{2}/{3}", csSheet.SecondaryTalentSpec, csSheet.SecondaryTalentPoints(1), csSheet.SecondaryTalentPoints(2), csSheet.SecondaryTalentPoints(3))
            End If
            Console.WriteLine()

            For Each pProfession As Profession In csSheet.Professions
                Console.WriteLine("{0}: {1}/{2}", pProfession.Name, pProfession.Skill, pProfession.Max)
            Next
            If csSheet.Professions.Count > 0 Then
                Console.WriteLine()
            End If

            Console.WriteLine("Health: {0} - {1}: {2}", csSheet.Health, csSheet.PowerType, csSheet.Power)
            Console.WriteLine()

            Console.WriteLine("Achievements: {0} - {1}/{2}", csSheet.AchievementPoints, csSheet.AchievementProgress.Earned, csSheet.AchievementProgress.Total)
            For Each aAchievements As Achievements In csSheet.AchievementCategories
                Console.WriteLine("  {0}: {1} - {2}/{3}", aAchievements.Name, aAchievements.Points, aAchievements.Earned, aAchievements.Total)
            Next
            Console.WriteLine()

            Console.WriteLine("Strength: {0} ({1} + {2}) Increases Attack Power by {3}", csSheet.Stats.Strength.Effective, csSheet.Stats.Strength.Base, csSheet.Stats.Strength.Effective - csSheet.Stats.Strength.Base, csSheet.Stats.Strength.AttackPower)
            Console.WriteLine("Agility: {0} ({1} + {2}) Increases Critical Hit chance by {3:P2}, Increases Armor by {4}", csSheet.Stats.Agility.Effective, csSheet.Stats.Agility.Base, csSheet.Stats.Agility.Effective - csSheet.Stats.Agility.Base, csSheet.Stats.Agility.CritHitPercent / 100, csSheet.Stats.Agility.Armor)
            Console.WriteLine("Stamina: {0} ({1} + {2}) Increases Health by {3}", csSheet.Stats.Stamina.Effective, csSheet.Stats.Stamina.Base, csSheet.Stats.Stamina.Effective - csSheet.Stats.Stamina.Base, csSheet.Stats.Stamina.Health)
            Console.WriteLine("Intellect: {0} ({1} + {2}) Increase Mana by {3}, Increases Spell Critical Hit by {4:P}", csSheet.Stats.Intellect.Effective, csSheet.Stats.Intellect.Base, csSheet.Stats.Intellect.Effective - csSheet.Stats.Intellect.Base, csSheet.Stats.Intellect.Mana, csSheet.Stats.Intellect.CritHitPercent / 100)
            Console.WriteLine("Spirit: {0} ({1} + {2}) Increases Health Regeneration by {3} Per Second while not in combat, Increases Mana Regeneration by {4} Per 5 Seconds while not casting", csSheet.Stats.Spirit.Effective, csSheet.Stats.Spirit.Base, csSheet.Stats.Spirit.Effective - csSheet.Stats.Spirit.Base, csSheet.Stats.Spirit.HealthRegen, csSheet.Stats.Spirit.ManaRegen)
            Console.WriteLine("Armor: {0} Reduces Physical Damage taken by {1:P2}", csSheet.Stats.Armor.Effective, csSheet.Stats.Armor.PercentDamageReduction / 100)
            Console.WriteLine()

            Console.WriteLine("Main Hand Damage: {0}-{1} - Damage per Second: {2:N1}", csSheet.Melee.MainHand.Min, csSheet.Melee.MainHand.Max, csSheet.Melee.MainHand.DPS)
            Console.WriteLine("Off Hand Damage: {0}-{1} - Damage per Second: {2:N1}", csSheet.Melee.OffHand.Min, csSheet.Melee.OffHand.Max, csSheet.Melee.OffHand.DPS)
            Console.WriteLine("Attack Speed: {0:N2} - Haste rating {1} ({2:P2} haste)", csSheet.Melee.MainHand.Speed, csSheet.Melee.MainHand.HasteRating, csSheet.Melee.MainHand.HastePercent / 100)
            Console.WriteLine("Melee Attack Power: {0} ({1} + {2}) Increases damage with melee weapons by {3:N1} damage per second", csSheet.Melee.AttackPower.Effective, csSheet.Melee.AttackPower.Base, csSheet.Melee.AttackPower.Effective - csSheet.Melee.AttackPower.Base, csSheet.Melee.AttackPower.IncreasedDPS)
            Console.WriteLine("Hit rating: {0} Increases your melee chance to hit a target of level {1} by {2:P2}, Armor penetration rating {3} (Enemy armor reduced by up to {4:P2})", csSheet.Melee.HitRating.Value, csSheet.Level, csSheet.Melee.HitRating.IncreasedHitPercent / 100, csSheet.Melee.HitRating.ArmorPenetrationRating, csSheet.Melee.HitRating.ArmorPenetrationPercent / 100)
            Console.WriteLine("Crit chance: {0:P2} Crit rating {1} (+{2:P2} crit chance)", csSheet.Melee.CritChance.Percent / 100, csSheet.Melee.CritChance.Rating, csSheet.Melee.CritChance.PlusPercent / 100)
            Console.WriteLine("Expertise: {0} Reduces chance to be dodged or parried by {1:P2}, Expertise rating {2} (+{3} expertise)", csSheet.Melee.Expertise.Value, csSheet.Melee.Expertise.Percent / 100, csSheet.Melee.Expertise.Rating, csSheet.Melee.Expertise.Additional)
            Console.WriteLine()

            Console.WriteLine("Ranged Damage: {0}-{1} - Damage per Second: {2:N1}", csSheet.Ranged.Weapon.Min, csSheet.Ranged.Weapon.Max, csSheet.Ranged.Weapon.DPS)
            Console.WriteLine("Attack Speed: {0:N2} - Haste rating {1} ({2:P2} haste)", csSheet.Ranged.Weapon.Speed, csSheet.Ranged.Weapon.HasteRating, csSheet.Ranged.Weapon.HastePercent / 100)
            Console.WriteLine("Ranged Attack Power: {0} ({1} + {2}) Increases damage with ranged weapons by {3:N1} damage per second", csSheet.Ranged.AttackPower.Effective, csSheet.Ranged.AttackPower.Base, csSheet.Ranged.AttackPower.Effective - csSheet.Ranged.AttackPower.Base, csSheet.Ranged.AttackPower.IncreasedDPS)
            Console.WriteLine("Hit rating: {0} Increases your ranged chance to hit a target of level {1} by {2:P2}, Armor penetration rating {3} (Enemy armor reduced by up to {4:P2})", csSheet.Ranged.HitRating.Value, csSheet.Level, csSheet.Ranged.HitRating.IncreasedHitPercent / 100, csSheet.Ranged.HitRating.ArmorPenetrationRating, csSheet.Ranged.HitRating.ArmorPenetrationPercent / 100)
            Console.WriteLine("Crit chance: {0:P2} Crit rating {1} (+{2:P2} crit chance)", csSheet.Ranged.CritChance.Percent / 100, csSheet.Ranged.CritChance.Rating, csSheet.Ranged.CritChance.PlusPercent / 100)
            Console.WriteLine()

            Console.WriteLine("Bonus Spell Damage - Holy {0} - Fire {1} - Nature {2} - Frost {3} - Shadow {4} - Arcane {5}", csSheet.Spell.SpellPower.Holy, csSheet.Spell.SpellPower.Fire, csSheet.Spell.SpellPower.Nature, csSheet.Spell.SpellPower.Frost, csSheet.Spell.SpellPower.Shadow, csSheet.Spell.SpellPower.Arcane)
            Console.WriteLine("Bonus Healing: {0}", csSheet.Spell.SpellPower.Healing)
            Console.WriteLine("Hit rating: {0} Increases your spell chance to hit a target of level {1} by {2:P2}, Spell Penetration {3} (Reduces enemy resistances by {4})", csSheet.Spell.HitRating.Value, csSheet.Level, csSheet.Spell.HitRating.IncreasedHitPercent / 100, csSheet.Spell.HitRating.Penetration, csSheet.Spell.HitRating.ReducedResistance)
            Console.WriteLine("Crit Rating: {0} - Holy {1:P2} - Fire {2:P2} - Nature {3:P2} - Frost {4:P2} - Shadow {5:P2} - Arcane {6:P2}", csSheet.Spell.CritChance.Rating, csSheet.Spell.CritChance.Holy / 100, csSheet.Spell.CritChance.Fire / 100, csSheet.Spell.CritChance.Nature / 100, csSheet.Spell.CritChance.Frost / 100, csSheet.Spell.CritChance.Shadow / 100, csSheet.Spell.CritChance.Arcane / 100)
            Console.WriteLine("Haste Rating: {0} Increases the speed that your spells cast by {1:P2}", csSheet.Spell.HasteRating, csSheet.Spell.HastePercent / 100)
            Console.WriteLine("Mana Regen: {0} mana regenerated every 5 seconds while not casting, {1} mana regenerated every 5 seconds while casting", csSheet.Spell.ManaRegenWhileNotCasting, csSheet.Spell.ManaRegenWhileCasting)
            Console.WriteLine()

            Console.WriteLine("Armor: {0} Reduces Physical Damage taken by {1:P2}", csSheet.Stats.Armor.Effective, csSheet.Stats.Armor.PercentDamageReduction / 100)
            Console.WriteLine("Defense: {0} Defense Rating {1} (+{2}), Increases chance to Dodge, Block and Parry by {3:P2}, Decreases chance to be hit and critically hit by {4:P2}", csSheet.Defense.Defense.Value, csSheet.Defense.Defense.Rating, csSheet.Defense.Defense.PlusDefense, csSheet.Defense.Defense.DecreasePercent / 100, csSheet.Defense.Defense.IncreasePercent / 100)
            Console.WriteLine("Dodge: {0:P2} - Dodge Rating: {1} Increases your chance to Dodge by {2:P2}", csSheet.Defense.Dodge.Percent / 100, csSheet.Defense.Dodge.Rating, csSheet.Defense.Dodge.IncreasePercent / 100)
            Console.WriteLine("Parry: {0:P2} - Parry Rating: {1} Increases your chance to Parry by {2:P2}", csSheet.Defense.Parry.Percent / 100, csSheet.Defense.Parry.Rating, csSheet.Defense.Parry.IncreasePercent / 100)
            Console.WriteLine("Block: {0:P2} - Block Rating: {1} Increases your chance to Block by {2:P2}", csSheet.Defense.Block.Percent / 100, csSheet.Defense.Block.Rating, csSheet.Defense.Block.IncreasePercent / 100)
            Console.WriteLine("Resilience: {0} - Reduces periodic damage and chance to be critically hit by {1:P2}, Reduces the effect of mana-drains and the damage of critical strikes by {2:P2}", csSheet.Defense.Resilience.Value, csSheet.Defense.Resilience.HitPercent / 100, csSheet.Defense.Resilience.DamagePercent / 100)
            Console.WriteLine()

            Console.WriteLine("Lifetime honorable kills: {0}", csSheet.LifetimeHonorKills)
            Console.WriteLine()

            For Each atTeam As ArenaTeam In csSheet.ArenaTeams
                Console.WriteLine("{0}v{0} arena team - {1}", atTeam.Size, atTeam.Name)
                Console.WriteLine("{0} rating - ranked {1} - {2} wins, {3} losses", atTeam.Rating, atTeam.Ranking, atTeam.SeasonGamesWon, atTeam.SeasonGamesPlayed - atTeam.SeasonGamesWon)
                For Each mMember As ArenaTeamMember In atTeam.Members
                    Console.WriteLine("  {0} - {1}-{2} - {3} rating", mMember.Name, mMember.SeasonGamesWon, mMember.SeasonGamesPlayed - mMember.SeasonGamesWon, mMember.PersonalRating)
                Next
                Console.WriteLine()
            Next

            Console.WriteLine("Press any key to continue.")
            Console.ReadKey(True)
        End Sub

        Private Sub CharacterStatisticsDemo()
            Console.Clear()
            Console.WriteLine("Character Statistics Demo")
            Console.WriteLine()

            Dim strCharacter As String
            Dim strRealm As String

            ' First, get the character
            Do
                Console.WriteLine("Please enter the name of the character whose statistics you wish to retrieve.")
                Console.Write(">")
                strCharacter = Console.ReadLine

                If String.IsNullOrEmpty(strCharacter) Then
                    Console.WriteLine("You must enter a character name.")
                    Console.WriteLine()
                Else
                    Exit Do
                End If
            Loop

            ' Next, get the realm
            Do
                Console.WriteLine("Please enter the name of the character's realm.")
                Console.Write(">")
                strRealm = Console.ReadLine

                If String.IsNullOrEmpty(strRealm) Then
                    Console.WriteLine("You must enter a realm.")
                    Console.WriteLine()
                Else
                    Exit Do
                End If
            Loop

            Dim csStatistics As New CharacterStatistics(strRealm, strCharacter)

            ' Display the statistics
            Do
                Console.Clear()
                Console.WriteLine("Statistics for {0}-{1}", strRealm, strCharacter)

                If csStatistics.RecentStatistics.Count > 0 Then
                    Console.WriteLine()
                    Console.WriteLine("Most recent statistics:")
                    For Each sStatistic As Statistic In csStatistics.RecentStatistics
                        Console.WriteLine("{0} - {1}", sStatistic.Name, sStatistic.Quantity)
                    Next
                End If

                Console.WriteLine()
                Console.WriteLine("Select a category")
                Console.WriteLine("  or press enter to exit")
                For Each cCategory As Statistics.CategoryInfo In csStatistics.Categories
                    Console.WriteLine("{0}) {1}", csStatistics.Categories.IndexOf(cCategory), cCategory.Name)
                Next

                Console.Write(">")
                Dim strResponse As String = Console.ReadLine
                If String.IsNullOrEmpty(strResponse) Then Exit Do
                Dim intResponse As Integer
                If Integer.TryParse(strResponse, intResponse) Then
                    If intResponse >= 0 And intResponse < csStatistics.Categories.Count Then
                        Console.Clear()
                        StatisticCategoryDetail(csStatistics.Categories(intResponse), csStatistics.CategoryStatistics(csStatistics.Categories(intResponse)).Statistics)
                        Console.WriteLine()
                        Console.WriteLine("Press any key to continue.")
                        Console.ReadKey(True)
                    End If
                End If
            Loop
        End Sub

        Private Sub StatisticCategoryDetail(ByRef cCategory As Statistics.CategoryInfo, ByRef cscCategory As Statistics.Category.Category)
            Console.WriteLine("{0} statistics", cCategory.Name)
            Console.WriteLine()
            For Each sStatistic As Statistic In cscCategory.Statistics
                StatisticDetail(sStatistic)
            Next
            For Each cSubcategory As Statistics.Category.Category In cscCategory.Subcategories
                StatisticSubcategoryDetail(cCategory.Subcategories(cscCategory.Subcategories.IndexOf(cSubcategory)), cSubcategory)
            Next
        End Sub

        Private Sub StatisticSubcategoryDetail(ByRef sCategory As Statistics.SubcategoryInfo, ByRef cscCategory As Statistics.Category.Category)
            Console.WriteLine()
            Console.WriteLine("{0} statistics", sCategory.Name)
            Console.WriteLine()
            For Each sStatistic As Statistic In cscCategory.Statistics
                StatisticDetail(sStatistic)
            Next
        End Sub

        Private Sub StatisticDetail(ByRef sStatistic As Statistic)
            If String.IsNullOrEmpty(sStatistic.Highest) Then
                Console.WriteLine("{0} - {1}", sStatistic.Name, sStatistic.Quantity)
            Else
                Console.WriteLine("{0} - {1} ({2})", sStatistic.Name, sStatistic.Highest, sStatistic.Quantity)
            End If
        End Sub

        Private Sub CharacterTalentsDemo()
            Console.Clear()
            Console.WriteLine("Character Talents Demo")
            Console.WriteLine()

            Dim strCharacter As String
            Dim strRealm As String

            ' First, get the character
            Do
                Console.WriteLine("Please enter the name of the character whose talents you wish to retrieve.")
                Console.Write(">")
                strCharacter = Console.ReadLine

                If String.IsNullOrEmpty(strCharacter) Then
                    Console.WriteLine("You must enter a character name.")
                    Console.WriteLine()
                Else
                    Exit Do
                End If
            Loop

            ' Next, get the realm
            Do
                Console.WriteLine("Please enter the name of the character's realm.")
                Console.Write(">")
                strRealm = Console.ReadLine

                If String.IsNullOrEmpty(strRealm) Then
                    Console.WriteLine("You must enter a realm.")
                    Console.WriteLine()
                Else
                    Exit Do
                End If
            Loop

            ' Do the lookup
            Dim ctTalents As New CharacterTalents(strRealm, strCharacter)

            ' Display the talents
            Console.Clear()
            Console.WriteLine("Character Talents for {0}-{1}", strRealm, strCharacter)
            Console.WriteLine()

            Console.WriteLine("Primary Talents")
            For Each tTree As Tree In ctTalents.PrimaryTalents.TalentTrees
                Console.WriteLine("  {0}", tTree.Name)
                For Each tTalent As Talent In tTree.Talents
                    Console.WriteLine("    {0} - {1}/{2}", tTalent.Name, tTalent.Points, tTalent.MaxPoints)
                    If tTalent.Points > 0 Then
                        Console.WriteLine("      {0}", tTalent.Ranks(tTalent.Points - 1))
                        If tTalent.SpellCastTime > 0 Then
                            Console.WriteLine("        {0:N2} second cast", tTalent.SpellCastTime)
                        End If
                        If tTalent.SpellCooldown > 0 Then
                            Console.WriteLine("        {0:N2} second cooldown", tTalent.SpellCooldown / 1000)
                        End If
                        If tTalent.SpellMaxRange > 0 Then
                            Console.WriteLine("        {0} yard range", tTalent.SpellMaxRange)
                        End If
                        For Each pPower As Power In tTalent.RequiredPower
                            Select Case pPower.PowerType
                                Case "mana"
                                    Console.WriteLine("          Requires {0} percent of base mana", pPower.Cost)
                                Case "energy"
                                    Console.WriteLine("          Requires {0} energy", pPower.Cost)
                                Case "rage"
                                    Console.WriteLine("          Requires {0} rage", pPower.Cost)
                                Case "runic"
                                    Console.WriteLine("          Requires {0} runic power", pPower.Cost)
                                Case "blood"
                                    Console.WriteLine("          Requires {0} blood rune{1}", pPower.Cost, IIf(pPower.Cost > 1, "s", ""))
                                Case "frost"
                                    Console.WriteLine("          Requires {0} frost rune{1}", pPower.Cost, IIf(pPower.Cost > 1, "s", ""))
                                Case "unholy"
                                    Console.WriteLine("          Requires {0} unholy rune{1}", pPower.Cost, IIf(pPower.Cost > 1, "s", ""))
                            End Select
                        Next
                    End If
                Next
                Console.WriteLine()
            Next

            Console.WriteLine("Primary Glyphs")
            For Each gGlyph As Glyph In ctTalents.PrimaryGlyphs
                Console.WriteLine("  {0} - {1} - {2}", gGlyph.GlyphType, gGlyph.Name, gGlyph.Effect)
            Next
            Console.WriteLine()

            If ctTalents.SecondaryTalents IsNot Nothing Then
                Console.WriteLine("Secondary Talents")
                For Each tTree As Tree In ctTalents.SecondaryTalents.TalentTrees
                    Console.WriteLine("  {0}", tTree.Name)
                    For Each tTalent As Talent In tTree.Talents
                        Console.WriteLine("    {0} - {1}/{2}", tTalent.Name, tTalent.Points, tTalent.MaxPoints)
                        If tTalent.Points > 0 Then
                            Console.WriteLine("      {0}", tTalent.Ranks(tTalent.Points - 1))
                            If tTalent.SpellCastTime > 0 Then
                                Console.WriteLine("        {0:N2} second cast", tTalent.SpellCastTime)
                            End If
                            If tTalent.SpellCooldown > 0 Then
                                Console.WriteLine("        {0:N2} second cooldown", tTalent.SpellCooldown / 1000)
                            End If
                            If tTalent.SpellMaxRange > 0 Then
                                Console.WriteLine("        {0} yard range", tTalent.SpellMaxRange)
                            End If
                            For Each pPower As Power In tTalent.RequiredPower
                                Select Case pPower.PowerType
                                    Case "mana"
                                        Console.WriteLine("          Requires {0} percent of base mana", pPower.Cost)
                                    Case "energy"
                                        Console.WriteLine("          Requires {0} energy", pPower.Cost)
                                    Case "rage"
                                        Console.WriteLine("          Requires {0} rage", pPower.Cost)
                                    Case "runic"
                                        Console.WriteLine("          Requires {0} runic power", pPower.Cost)
                                    Case "blood"
                                        Console.WriteLine("          Requires {0} blood rune{1}", pPower.Cost, IIf(pPower.Cost > 1, "s", ""))
                                    Case "frost"
                                        Console.WriteLine("          Requires {0} frost rune{1}", pPower.Cost, IIf(pPower.Cost > 1, "s", ""))
                                    Case "unholy"
                                        Console.WriteLine("          Requires {0} unholy rune{1}", pPower.Cost, IIf(pPower.Cost > 1, "s", ""))
                                End Select
                            Next
                        End If
                    Next
                    Console.WriteLine()
                Next

                Console.WriteLine("Secondary Glyphs")
                For Each gGlyph As Glyph In ctTalents.SecondaryGlyphs
                    Console.WriteLine("  {0} - {1} - {2}", gGlyph.GlyphType, gGlyph.Name, gGlyph.Effect)
                Next
                Console.WriteLine()
            End If

            For Each pPet As Pet In ctTalents.Pets
                Console.WriteLine("Talents for pet {0}, Level {1} {2} ({3})", pPet.Name, pPet.Level, pPet.Family, pPet.NPCName)
                Console.WriteLine("  {0}", pPet.Talents.Name)
                For Each tTalent As Talent In pPet.Talents.Talents
                    Console.WriteLine("    {0} - {1}/{2}", tTalent.Name, tTalent.Points, tTalent.MaxPoints)
                    If tTalent.Points > 0 Then
                        Console.WriteLine("      {0}", tTalent.Ranks(tTalent.Points - 1))
                        If tTalent.SpellCastTime > 0 Then
                            Console.WriteLine("        {0:N2} second cast", tTalent.SpellCastTime)
                        End If
                        If tTalent.SpellCooldown > 0 Then
                            Console.WriteLine("        {0:N2} second cooldown", tTalent.SpellCooldown / 1000)
                        End If
                        If tTalent.SpellMaxRange > 0 Then
                            Console.WriteLine("        {0} yard range", tTalent.SpellMaxRange)
                        End If
                        For Each pPower As Power In tTalent.RequiredPower
                            Select Case pPower.PowerType
                                Case "mana"
                                    Console.WriteLine("          Requires {0} percent of base mana", pPower.Cost)
                                Case "energy"
                                    Console.WriteLine("          Requires {0} energy", pPower.Cost)
                                Case "rage"
                                    Console.WriteLine("          Requires {0} rage", pPower.Cost)
                                Case "runic"
                                    Console.WriteLine("          Requires {0} runic power", pPower.Cost)
                                Case "blood"
                                    Console.WriteLine("          Requires {0} blood rune{1}", pPower.Cost, IIf(pPower.Cost > 1, "s", ""))
                                Case "frost"
                                    Console.WriteLine("          Requires {0} frost rune{1}", pPower.Cost, IIf(pPower.Cost > 1, "s", ""))
                                Case "unholy"
                                    Console.WriteLine("          Requires {0} unholy rune{1}", pPower.Cost, IIf(pPower.Cost > 1, "s", ""))
                            End Select
                        Next
                    End If
                Next
                Console.WriteLine()
            Next

            Console.WriteLine("Press any key to continue.")
            Console.ReadKey(True)
        End Sub

        Private Sub DungeonDemo()
            Console.Clear()
            Console.WriteLine("Dungeon Data Demo")
            Console.WriteLine()

            Dim dDungeons As New Dungeons

            For Each dDungeon As LibWowArmory.Dungeon.Dungeon In dDungeons.Dungeons
                Console.WriteLine("{0} ({1}-{2}, {3}-man {4}) - {5} - {6}", dDungeon.Name, dDungeon.LevelMin, dDungeon.LevelMax, dDungeon.PartySize, If(dDungeon.Raid, "raid", "dungeon"), If(dDungeon.HasHeroic, "Heroic available", "No heroic available"), [Enum].GetName(GetType(Enums.ReleaseType), CType(dDungeon.Release, Enums.ReleaseType)))
                For Each bBoss As LibWowArmory.Dungeon.Boss In dDungeon.Bosses
                    Console.WriteLine("  {0}", bBoss.Name)
                Next
                Console.WriteLine()
            Next

            Console.WriteLine("Press any key to continue.")
            Console.ReadKey(True)
        End Sub

        Private Sub FactionsDemo()
            Console.Clear()
            Console.WriteLine("Factions Demo")
            Console.WriteLine()

            Dim fFactions As New Factions

            For Each fFaction As Faction In fFactions.Factions
                Console.WriteLine("{0} - {1}", fFaction.Name, [Enum].GetName(GetType(Enums.ReleaseType), CType(fFaction.Release, Enums.ReleaseType)))
            Next

            Console.WriteLine()
            Console.WriteLine("Press any key to continue.")
            Console.ReadKey(True)
        End Sub

        Private Sub ItemInfoDemo()
            Console.Clear()
            Console.WriteLine("Item Info Demo")
            Console.WriteLine()

            Dim intItemID As Integer

            ' Get the item number
            Do
                Console.WriteLine("Please enter the ID number of the item you wish to lookup.")
                Console.Write(">")
                Dim strItemID As Integer = Console.ReadLine

                If String.IsNullOrEmpty(strItemID) Then
                    Console.WriteLine("You must enter an item number.")
                    Console.WriteLine()
                ElseIf Not Integer.TryParse(strItemID, intItemID) Then
                    Console.WriteLine("You must enter an item number.")
                    Console.WriteLine()
                Else
                    Exit Do
                End If
            Loop

            Dim iiItemInfo As New ItemInfo(intItemID)

            ' Display the item's information
            Console.Clear()
            Console.WriteLine("{0} - {1} iLevel {2} - {3}", iiItemInfo.Name, [Enum].GetName(GetType(Enums.RarityType), iiItemInfo.Quality), iiItemInfo.Level, iiItemInfo.ItemType)
            If iiItemInfo.FactionRestriction <> Enums.FactionType.None Then
                Console.WriteLine("Restricted to {0}", iiItemInfo.FactionRestriction)
                Console.WriteLine("Equivalent items:")
                For Each tfiItem As TranslationForItem In iiItemInfo.TranslationFor
                    Console.WriteLine("  {0}: {1} - {2}", tfiItem.Faction, tfiItem.ItemID, tfiItem.Name)
                Next
            End If
            Console.WriteLine()

            If iiItemInfo.RandomProperties.Count > 0 Then
                Console.WriteLine("Random Enchantment Properties:")
                For Each rpProperty As RandomProperty In iiItemInfo.RandomProperties
                    Console.WriteLine("  {0} - {1}", rpProperty.Suffix, rpProperty.Enchantments)
                Next
                Console.WriteLine()
            End If

            If Not String.IsNullOrEmpty(iiItemInfo.RequiredAbility) Then
                Console.WriteLine("Required ability: {0}", iiItemInfo.RequiredAbility)
                Console.WriteLine()
            End If

            If Not String.IsNullOrEmpty(iiItemInfo.RequiredSkill) Then
                Console.WriteLine("Required skill: {0} ({1})", iiItemInfo.RequiredSkill, iiItemInfo.RequiredSkillRank)
                Console.WriteLine()
            End If

            If iiItemInfo.Cost IsNot Nothing Then
                Console.WriteLine("Costs:")
                If iiItemInfo.Cost.Faction <> Enums.FactionType.None Then
                    Console.WriteLine("  Only purchasable by {0}", [Enum].GetName(GetType(Enums.FactionType), iiItemInfo.Cost.Faction))
                End If
                If iiItemInfo.Cost.BuyPrice > 0 Then
                    Console.WriteLine("  Buy price: {0}g {1}s {2}c", Math.Floor(iiItemInfo.Cost.BuyPrice / 10000), Math.Floor(iiItemInfo.Cost.BuyPrice / 100) Mod 100, iiItemInfo.Cost.BuyPrice Mod 100)
                End If
                If iiItemInfo.Cost.SellPrice > 0 Then
                    Console.WriteLine("  Sell price: {0}g {1}s {2}c", Math.Floor(iiItemInfo.Cost.SellPrice / 10000), Math.Floor(iiItemInfo.Cost.SellPrice / 100) Mod 100, iiItemInfo.Cost.SellPrice Mod 100)
                End If
                If iiItemInfo.Cost.Arena > 0 Then
                    Console.WriteLine("  {0} arena points", iiItemInfo.Cost.Arena)
                End If
                If iiItemInfo.Cost.Honor > 0 Then
                    Console.WriteLine("  {0} honor points", iiItemInfo.Cost.Honor)
                End If
                For Each tToken As TokenCost In iiItemInfo.Cost.Token
                    Console.WriteLine("  {0} {1}", tToken.Count, tToken.Item)
                Next
                Console.WriteLine()
            End If

            If iiItemInfo.CurrencyFor.Count > 0 Then
                Console.WriteLine("Currency for:")
                For Each ciItem As CurrencyItem In iiItemInfo.CurrencyFor
                    Console.WriteLine("  {0}", ciItem.Name)
                Next
                Console.WriteLine()
            End If

            If iiItemInfo.Vendors.Count > 0 Then
                Console.WriteLine("Vendors bought from:")
                For Each cVendor As Creature In iiItemInfo.Vendors
                    Console.WriteLine("  {0} - {1}", cVendor.Name, cVendor.Area)
                Next
                Console.WriteLine()
            End If

            If iiItemInfo.StartsQuest IsNot Nothing Then
                Console.WriteLine("Starts quest: {0} - {1}", iiItemInfo.StartsQuest.Name, iiItemInfo.StartsQuest.Area)
                Console.WriteLine()
            End If

            If iiItemInfo.ProvidedForQuests.Count > 0 Then
                Console.WriteLine("Provided for quests:")
                For Each qQuest As Quest In iiItemInfo.ProvidedForQuests
                    Console.WriteLine("  {0} - {1}", qQuest.Name, qQuest.Area)
                Next
                Console.WriteLine()
            End If

            If iiItemInfo.ObjectiveOfQuests.Count > 0 Then
                Console.WriteLine("Objective of quests:")
                For Each qQuest As Quest In iiItemInfo.ObjectiveOfQuests
                    Console.WriteLine("  {0} - {1}", qQuest.Name, qQuest.Area)
                Next
                Console.WriteLine()
            End If

            If iiItemInfo.RewardFromQuests.Count > 0 Then
                Console.WriteLine("Reward from quests:")
                For Each qQuest As Quest In iiItemInfo.RewardFromQuests
                    Console.WriteLine("  {0} - {1}", qQuest.Name, qQuest.Area)
                Next
                Console.WriteLine()
            End If

            If iiItemInfo.MultiLoot Or iiItemInfo.MultiLootQuest Then
                Console.WriteLine("This item will drop for everyone in the party.")
                Console.WriteLine()
            End If

            If iiItemInfo.CreatedBy IsNot Nothing Then
                Console.WriteLine("Created by {0}", iiItemInfo.CreatedBy.Name)
                For Each rReagent As Reagent In iiItemInfo.CreatedBy.Reagents
                    Console.WriteLine("  {0}x {1}", rReagent.Count, rReagent.Name)
                Next
                Console.WriteLine()
            End If

            If iiItemInfo.ReagentFor.Count > 0 Then
                Console.WriteLine("Reagent for:")
                For Each siSpell As SpellItem In iiItemInfo.ReagentFor
                    Console.WriteLine("  {0}", siSpell.Name)
                Next
                Console.WriteLine()
            End If

            If iiItemInfo.DisenchantLoot.Count > 0 Then
                Console.WriteLine("Disenchant information:")
                Console.WriteLine("  Requires Enchanting ({0})", iiItemInfo.DisenchantLootSkillRank)
                For Each diItem As DisenchantItem In iiItemInfo.DisenchantLoot
                    Console.WriteLine("  {0} - {1}", diItem.Name, [Enum].GetName(GetType(Enums.DropRateType), diItem.DropRate))
                Next
                Console.WriteLine()
            End If

            If iiItemInfo.ContainerObjects.Count > 0 Then
                Console.WriteLine("Found in:")
                For Each oObject As ContainerObject In iiItemInfo.ContainerObjects
                    Console.WriteLine("  {0} - {1} - {2}", oObject.Name, oObject.Area, [Enum].GetName(GetType(Enums.DropRateType), oObject.DropRate))
                Next
                Console.WriteLine()
            End If

            If iiItemInfo.DropGeneralCreatures IsNot Nothing Then
                Console.WriteLine("Drops in:")
                For Each aiArea As AreaInfo In iiItemInfo.DropGeneralCreatures.Area
                    Console.WriteLine("  {0}", aiArea.Name)
                Next
                Console.WriteLine("Drops from:")
                For Each ciCreature As CreatureType In iiItemInfo.DropGeneralCreatures.CreatureTypes
                    Console.WriteLine("  {0}", ciCreature.Name)
                Next
                Console.WriteLine()
            End If

            If iiItemInfo.DropSpecificCreatures.Count > 0 Then
                Console.WriteLine("Drops from:")
                For Each cCreature As Creature In iiItemInfo.DropSpecificCreatures
                    Console.WriteLine("  {0} - {1}", cCreature.Name, cCreature.Area)
                Next
                Console.WriteLine()
            End If

            If iiItemInfo.HerbGeneralCreatures IsNot Nothing Then
                Console.WriteLine("Herbed in:")
                For Each aiArea As AreaInfo In iiItemInfo.HerbGeneralCreatures.Area
                    Console.WriteLine("  {0}", aiArea.Name)
                Next
                Console.WriteLine("Herbed from:")
                For Each ciCreature As CreatureType In iiItemInfo.HerbGeneralCreatures.CreatureTypes
                    Console.WriteLine("  {0}", ciCreature.Name)
                Next
                Console.WriteLine()
            End If

            If iiItemInfo.HerbSpecificCreatures.Count > 0 Then
                Console.WriteLine("Herbed from:")
                For Each cCreature As Creature In iiItemInfo.HerbSpecificCreatures
                    Console.WriteLine("  {0} - {1}", cCreature.Name, cCreature.Area)
                Next
                Console.WriteLine()
            End If

            If iiItemInfo.MineGeneralCreatures IsNot Nothing Then
                Console.WriteLine("Mined in:")
                For Each aiArea As AreaInfo In iiItemInfo.MineGeneralCreatures.Area
                    Console.WriteLine("  {0}", aiArea.Name)
                Next
                Console.WriteLine("Mined from:")
                For Each ciCreature As CreatureType In iiItemInfo.MineGeneralCreatures.CreatureTypes
                    Console.WriteLine("  {0}", ciCreature.Name)
                Next
                Console.WriteLine()
            End If

            If iiItemInfo.MineSpecificCreatures.Count > 0 Then
                Console.WriteLine("Mined from:")
                For Each cCreature As Creature In iiItemInfo.MineSpecificCreatures
                    Console.WriteLine("  {0} - {1}", cCreature.Name, cCreature.Area)
                Next
                Console.WriteLine()
            End If

            If iiItemInfo.PickPocketGeneralCreatures IsNot Nothing Then
                Console.WriteLine("Pick pocketed in:")
                For Each aiArea As AreaInfo In iiItemInfo.PickPocketGeneralCreatures.Area
                    Console.WriteLine("  {0}", aiArea.Name)
                Next
                Console.WriteLine("Pick pocketed from:")
                For Each ciCreature As CreatureType In iiItemInfo.PickPocketGeneralCreatures.CreatureTypes
                    Console.WriteLine("  {0}", ciCreature.Name)
                Next
                Console.WriteLine()
            End If

            If iiItemInfo.PickPocketSpecificCreatures.Count > 0 Then
                Console.WriteLine("Pick pocketed from:")
                For Each cCreature As Creature In iiItemInfo.PickPocketSpecificCreatures
                    Console.WriteLine("  {0} - {1}", cCreature.Name, cCreature.Area)
                Next
                Console.WriteLine()
            End If

            If iiItemInfo.SkinGeneralCreatures IsNot Nothing Then
                Console.WriteLine("Skined in:")
                For Each aiArea As AreaInfo In iiItemInfo.SkinGeneralCreatures.Area
                    Console.WriteLine("  {0}", aiArea.Name)
                Next
                Console.WriteLine("Skined from:")
                For Each ciCreature As CreatureType In iiItemInfo.SkinGeneralCreatures.CreatureTypes
                    Console.WriteLine("  {0}", ciCreature.Name)
                Next
                Console.WriteLine()
            End If

            If iiItemInfo.SkinSpecificCreatures.Count > 0 Then
                Console.WriteLine("Skined from:")
                For Each cCreature As Creature In iiItemInfo.SkinSpecificCreatures
                    Console.WriteLine("  {0} - {1}", cCreature.Name, cCreature.Area)
                Next
                Console.WriteLine()
            End If

            Console.WriteLine("Press any key to continue.")
            Console.ReadKey(True)
        End Sub

        Private Sub ItemSearchDemo()
            Dim qfQuery As New QueryFilter

            Dim dDungeons As New Dungeons
            Dim fFactions As New Factions

            Console.Clear()
            Console.WriteLine("Item Search Demo")
            Console.WriteLine()

            ' Set the parameters for the search
            Do
                Console.WriteLine("Select an option below to modify the filter.")
                Console.WriteLine("1) Source: {0}", [Enum].GetName(GetType(Enums.SourceType), qfQuery.Source.SourceFilter))
                Select Case qfQuery.Source.SourceFilter
                    Case Enums.SourceFilterType.DungeonsAndRaidDrops
                        If (qfQuery.Source.DungeonType = Enums.DungeonType.AllDungeonsAndRaids And qfQuery.Source.DungeonFilter = "all") Or qfQuery.Source.DungeonType <> Enums.DungeonType.AllDungeonsAndRaids Then
                            Console.WriteLine("   Drops from: {0}", [Enum].GetName(GetType(Enums.DungeonType), qfQuery.Source.DungeonType))
                            Select Case qfQuery.Source.DungeonType
                                Case Enums.DungeonType.DungeonsOnly
                                    Console.WriteLine("   Difficulty: {0}", [Enum].GetName(GetType(Enums.DifficultyType), qfQuery.Source.DifficultyFilter))
                            End Select
                        Else
                            Dim dDungeon As LibWowArmory.Dungeon.Dungeon = dDungeons.Dungeons.Where(Function(d) d.Key = qfQuery.Source.DungeonFilter).First
                            Console.WriteLine("   Drops from: {0}", dDungeon.Name)
                            If qfQuery.Source.BossFilter = 0 Then
                                Console.WriteLine("   Boss: All {0} Bosses", dDungeon.Name)
                            Else
                                Console.WriteLine("   Boss: {0}", dDungeon.Bosses.Where(Function(b) b.BossID = qfQuery.Source.BossFilter).First.Name)
                            End If
                            If dDungeon.HasHeroic Then
                                Console.WriteLine("   Difficulty: {0}", [Enum].GetName(GetType(Enums.DifficultyType), qfQuery.Source.DifficultyFilter))
                            End If
                        End If
                    Case Enums.SourceFilterType.PvpRewardsAlliance
                        Console.WriteLine("   PvP Source: {0}", [Enum].GetName(GetType(Enums.PvpAllianceSourceType), qfQuery.Source.PvpAllianceFilter))
                    Case Enums.SourceFilterType.PvpRewardsHorde
                        Console.WriteLine("   PvP Source: {0}", [Enum].GetName(GetType(Enums.PvpHordeSourceType), qfQuery.Source.PvpHordeFilter))
                    Case Enums.SourceFilterType.ReputationRewards
                        If qfQuery.Source.FactionFilter = -1 Then
                            Console.WriteLine("   Faction: All Factions")
                        Else
                            Console.WriteLine("   Faction: {0}", fFactions.Factions.ToArray.Where(Function(f) f.FactionID = qfQuery.Source.FactionFilter).First.Name)
                        End If
                End Select

                Console.WriteLine("2) Item Type: {0}", [Enum].GetName(GetType(Enums.ItemTypeType), qfQuery.ItemType.ItemTypeFilter))
                Select Case qfQuery.ItemType.ItemTypeFilter
                    Case Enums.ItemTypeType.AllItems
                        Console.WriteLine("   Desired by: {0} - {1}", [Enum].GetName(GetType(Enums.DesiredByType), qfQuery.ItemType.DesiredByFilter), [Enum].GetName(GetType(Enums.DesiredByRoleType), qfQuery.ItemType.DesiredByRoleFilter))
                        Console.WriteLine("   Required level: {0} to {1}", qfQuery.ItemType.RequiredLevelMinFilter, qfQuery.ItemType.RequiredLevelMaxFilter)
                        Console.WriteLine("   Rarity: {0}", [Enum].GetName(GetType(Enums.RarityType), qfQuery.ItemType.RarityFilter))
                    Case Enums.ItemTypeType.Armor
                        Console.WriteLine("   Desired by: {0} - {1}", [Enum].GetName(GetType(Enums.DesiredByType), qfQuery.ItemType.DesiredByFilter), [Enum].GetName(GetType(Enums.DesiredByRoleType), qfQuery.ItemType.DesiredByRoleFilter))
                        Console.WriteLine("   Slot: {0}", [Enum].GetName(GetType(Enums.ArmorSlotType), qfQuery.ItemType.ArmorSlotFilter))
                        Console.WriteLine("   Armor Type: {0}", [Enum].GetName(GetType(Enums.ArmorTypeType), qfQuery.ItemType.ArmorTypeFilter))
                        Console.WriteLine("   Required level: {0} to {1}", qfQuery.ItemType.RequiredLevelMinFilter, qfQuery.ItemType.RequiredLevelMaxFilter)
                        Console.WriteLine("   Rarity: {0}", [Enum].GetName(GetType(Enums.RarityType), qfQuery.ItemType.RarityFilter))
                    Case Enums.ItemTypeType.Consumables
                        Console.WriteLine("   Rarity: {0}", [Enum].GetName(GetType(Enums.RarityType), qfQuery.ItemType.RarityFilter))
                    Case Enums.ItemTypeType.Containers
                        Console.WriteLine("   Bag Type: {0}", [Enum].GetName(GetType(Enums.BagTypeType), qfQuery.ItemType.ContainerTypeFilter))
                    Case Enums.ItemTypeType.EnchantmentsPermanent
                        Console.WriteLine("   Slot: {0}", [Enum].GetName(GetType(Enums.PermanentEnchantmentSlotType), qfQuery.ItemType.PermanentEnchantmentSlotFilter))
                        Console.WriteLine("   Rarity: {0}", [Enum].GetName(GetType(Enums.RarityType), qfQuery.ItemType.RarityFilter))
                    Case Enums.ItemTypeType.EnchantmentsTemporary
                        Console.WriteLine("   Rarity: {0}", [Enum].GetName(GetType(Enums.RarityType), qfQuery.ItemType.RarityFilter))
                    Case Enums.ItemTypeType.Gems
                        Console.WriteLine("   Desired by: {0} - {1}", [Enum].GetName(GetType(Enums.DesiredByType), qfQuery.ItemType.DesiredByFilter), [Enum].GetName(GetType(Enums.DesiredByRoleType), qfQuery.ItemType.DesiredByRoleFilter))
                        Console.WriteLine("   Gem Type: {0}", [Enum].GetName(GetType(Enums.GemTypeType), qfQuery.ItemType.GemTypeFilter))
                        Console.WriteLine("   Rarity: {0}", [Enum].GetName(GetType(Enums.RarityType), qfQuery.ItemType.RarityFilter))
                    Case Enums.ItemTypeType.Glyphs
                        Console.WriteLine("   Desired by: {0} - {1}", [Enum].GetName(GetType(Enums.DesiredByType), qfQuery.ItemType.DesiredByFilter), [Enum].GetName(GetType(Enums.DesiredByRoleType), qfQuery.ItemType.DesiredByRoleFilter))
                    Case Enums.ItemTypeType.Miscellaneous
                        Console.WriteLine("   Rarity: {0}", [Enum].GetName(GetType(Enums.RarityType), qfQuery.ItemType.RarityFilter))
                    Case Enums.ItemTypeType.Projectiles
                        Console.WriteLine("   Type: {0}", [Enum].GetName(GetType(Enums.ProjectileTypeType), qfQuery.ItemType.ProjectilesTypeFilter))
                        Console.WriteLine("   Rarity: {0}", [Enum].GetName(GetType(Enums.RarityType), qfQuery.ItemType.RarityFilter))
                    Case Enums.ItemTypeType.Quivers
                        Console.WriteLine("   Type: {0}", [Enum].GetName(GetType(Enums.QuiverTypeType), qfQuery.ItemType.QuiverTypeFilter))
                    Case Enums.ItemTypeType.Reagents
                        Console.WriteLine("   Rarity: {0}", [Enum].GetName(GetType(Enums.RarityType), qfQuery.ItemType.RarityFilter))
                    Case Enums.ItemTypeType.Recipes
                        Console.WriteLine("   Recipes: {0}", [Enum].GetName(GetType(Enums.RecipesTypeType), qfQuery.ItemType.RecipesTypeFilter))
                        Console.WriteLine("   Rarity: {0}", [Enum].GetName(GetType(Enums.RarityType), qfQuery.ItemType.RarityFilter))
                        Console.WriteLine("   Skill Level: {0} - {1}", qfQuery.ItemType.SkillLevelMinFilter, qfQuery.ItemType.SkillLevelMaxFilter)
                    Case Enums.ItemTypeType.TradeGoods
                        Console.WriteLine("   Rarity: {0}", [Enum].GetName(GetType(Enums.RarityType), qfQuery.ItemType.RarityFilter))
                    Case Enums.ItemTypeType.Weapons
                        Console.WriteLine("   Desired by: {0} - {1}", [Enum].GetName(GetType(Enums.DesiredByType), qfQuery.ItemType.DesiredByFilter), [Enum].GetName(GetType(Enums.DesiredByRoleType), qfQuery.ItemType.DesiredByRoleFilter))
                        Console.WriteLine("   Slot: {0}", [Enum].GetName(GetType(Enums.WeaponSlotType), qfQuery.ItemType.WeaponSlotFilter))
                        Console.WriteLine("   Weapon Type: {0}", [Enum].GetName(GetType(Enums.WeaponTypeType), qfQuery.ItemType.WeaponTypeFilter))
                        Console.WriteLine("   Required level: {0} to {1}", qfQuery.ItemType.RequiredLevelMinFilter, qfQuery.ItemType.RequiredLevelMaxFilter)
                        Console.WriteLine("   Rarity: {0}", [Enum].GetName(GetType(Enums.RarityType), qfQuery.ItemType.RarityFilter))
                End Select
                If qfQuery.AdvancedOptions.Count > 0 Then
                    Console.WriteLine("   Advanced Filters:")
                    For Each aofFilter As AdvancedOptionsFilter In qfQuery.AdvancedOptions
                        If aofFilter.AdvancedOptionsFilter <= Enums.AdvancedOptionsType.Weapon_Speed Then
                            Dim strOperator As String = ""
                            Select Case aofFilter.OperatorFilter
                                Case Enums.AdvancedOptionsOperatorType.EqualTo
                                    strOperator = "="
                                Case Enums.AdvancedOptionsOperatorType.GreaterThan
                                    strOperator = ">"
                                Case Enums.AdvancedOptionsOperatorType.GreaterThanEqualTo
                                    strOperator = ">="
                                Case Enums.AdvancedOptionsOperatorType.LessThan
                                    strOperator = "<"
                                Case Enums.AdvancedOptionsOperatorType.LessThanEqualTo
                                    strOperator = "<="
                            End Select
                            Console.WriteLine("     {0} {1} {2}", [Enum].GetName(GetType(Enums.AdvancedOptionsType), aofFilter.AdvancedOptionsFilter), strOperator, aofFilter.RangeFilter)
                        Else
                            Console.WriteLine("     {0}", [Enum].GetName(GetType(Enums.AdvancedOptionsType), aofFilter.AdvancedOptionsFilter))
                        End If
                    Next
                End If
                Console.WriteLine("3) Search Query: {0}", qfQuery.SearchQuery)
                Console.WriteLine()
                Console.WriteLine("4) Perform Search")
                Console.WriteLine()

                Console.Write(">")
                Dim strResponse As String = Console.ReadLine
                Dim intResponse As Integer
                If Integer.TryParse(strResponse, intResponse) Then
                    If intResponse >= 1 And intResponse <= 4 Then
                        Select Case intResponse
                            Case 1
                                Console.Clear()
                                Console.WriteLine("Source Selection")
                                Console.WriteLine()
                                Do
                                    Console.WriteLine("Select a source:")
                                    Console.WriteLine("0) All Sources")
                                    Console.WriteLine("1) Dungeons and Raid Drops")
                                    Console.WriteLine("2) Reputation Rewards")
                                    Console.WriteLine("3) Quest Rewards")
                                    Console.WriteLine("4) PvP Rewards - Alliance")
                                    Console.WriteLine("5) PvP Rewards - Horde")
                                    Console.WriteLine("6) Exit")
                                    Console.WriteLine()

                                    Console.Write(">")
                                    Dim strResponse2 As String = Console.ReadLine
                                    Dim intResponse2 As Integer
                                    If Integer.TryParse(strResponse2, intResponse2) Then
                                        If intResponse2 >= 0 And intResponse2 <= 6 Then
                                            Select Case intResponse2
                                                Case 0
                                                    qfQuery.Source.SourceFilter = Enums.SourceFilterType.AllSources
                                                Case 1
                                                    qfQuery.Source.SourceFilter = Enums.SourceFilterType.DungeonsAndRaidDrops
                                                    Console.Clear()
                                                    Console.WriteLine("Dungeon and Raid Selection")
                                                    Console.WriteLine()
                                                    Do
                                                        Console.WriteLine("Select a dungeon and raid source")
                                                        Console.WriteLine()
                                                        Console.WriteLine("0) All Dungeons and Raids")
                                                        Console.WriteLine("1) Dungeons Only")
                                                        Console.WriteLine("2) Raids Only")
                                                        Console.WriteLine("3) Badge of Justice Rewards")
                                                        Console.WriteLine("4) Emblem of Heroism Rewards")
                                                        Console.WriteLine("5) Emblem of Valor Rewards")
                                                        Console.WriteLine("6) Emblem of Conquest Rewards")
                                                        Console.WriteLine("7) Choose a specific dungeon")
                                                        Console.WriteLine("8) Exit")
                                                        Console.WriteLine()

                                                        Console.Write(">")
                                                        Dim strResponse3 As String = Console.ReadLine
                                                        Dim intResponse3 As Integer
                                                        If Integer.TryParse(strResponse3, intResponse3) Then
                                                            If intResponse3 >= 0 And intResponse3 <= 8 Then
                                                                Select Case intResponse3
                                                                    Case 0
                                                                        qfQuery.Source.DungeonType = Enums.DungeonType.AllDungeonsAndRaids
                                                                    Case 1
                                                                        qfQuery.Source.DungeonType = Enums.DungeonType.DungeonsOnly
                                                                        qfQuery.Source.DifficultyFilter = SelectDifficulty()
                                                                    Case 2
                                                                        qfQuery.Source.DungeonType = Enums.DungeonType.RaidsOnly
                                                                    Case 3
                                                                        qfQuery.Source.DungeonType = Enums.DungeonType.BadgeOfJusticeRewards
                                                                    Case 4
                                                                        qfQuery.Source.DungeonType = Enums.DungeonType.EmblemOfHeroism
                                                                    Case 5
                                                                        qfQuery.Source.DungeonType = Enums.DungeonType.EmblemOfValor
                                                                    Case 6
                                                                        qfQuery.Source.DungeonType = Enums.DungeonType.EmblemOfConquest
                                                                    Case 7
                                                                        qfQuery.Source.DungeonFilter = SelectDungeon(dDungeons)
                                                                        If qfQuery.Source.DungeonFilter <> "all" Then
                                                                            Dim dDungeon As LibWowArmory.Dungeon.Dungeon = dDungeons.Dungeons.Where(Function(d) d.Key = qfQuery.Source.DungeonFilter).First
                                                                            qfQuery.Source.BossFilter = SelectBoss(dDungeon)
                                                                            If dDungeon.HasHeroic Then
                                                                                qfQuery.Source.DifficultyFilter = SelectDifficulty()
                                                                            End If
                                                                        End If
                                                                End Select
                                                                Console.Clear()
                                                                Exit Do
                                                            End If
                                                        End If
                                                        Console.Clear()
                                                        Console.WriteLine("Invalid selection.  Please try again.")
                                                        Console.WriteLine()
                                                    Loop
                                                Case 2
                                                    qfQuery.Source.SourceFilter = Enums.SourceFilterType.ReputationRewards
                                                    qfQuery.Source.FactionFilter = SelectFaction(fFactions)
                                                Case 3
                                                    qfQuery.Source.SourceFilter = Enums.SourceFilterType.QuestRewards
                                                Case 4
                                                    qfQuery.Source.SourceFilter = Enums.SourceFilterType.PvpRewardsAlliance
                                                    qfQuery.Source.PvpAllianceFilter = SelectPvpAllianceSource()
                                                Case 5
                                                    qfQuery.Source.SourceFilter = Enums.SourceFilterType.PvpRewardsHorde
                                                    qfQuery.Source.PvpHordeFilter = SelectPvpHordeSource()
                                            End Select
                                            Console.Clear()
                                            Exit Do
                                        End If
                                    End If
                                    Console.Clear()
                                    Console.WriteLine("Invalid source.  Please try again.")
                                    Console.WriteLine()
                                Loop
                            Case 2
                                Do
                                    Console.Clear()
                                    Console.WriteLine("Item Type Selection")
                                    Console.WriteLine()

                                    Console.WriteLine("Select an item type:")
                                    Console.WriteLine("0) All Items")
                                    Console.WriteLine("1) Weapons")
                                    Console.WriteLine("2) Armor")
                                    Console.WriteLine("3) Gems")
                                    Console.WriteLine("4) Containers")
                                    Console.WriteLine("5) Consumables")
                                    Console.WriteLine("6) Trade Goods")
                                    Console.WriteLine("7) Projectiles")
                                    Console.WriteLine("8) Quivers")
                                    Console.WriteLine("9) Recipes")
                                    Console.WriteLine("10) Reagents")
                                    Console.WriteLine("11) Miscellaneous")
                                    Console.WriteLine("12) Permanent Enchantments")
                                    Console.WriteLine("13) Temporary Enchantments")
                                    Console.WriteLine("14) Mounts")
                                    Console.WriteLine("15) Small Pets")
                                    Console.WriteLine("16) Keys")
                                    Console.WriteLine("17) Glyphs")

                                    Console.WriteLine()
                                    Console.Write(">")

                                    Dim strResponse2 As String = Console.ReadLine
                                    If String.IsNullOrEmpty(strResponse2) Then
                                        Console.Clear()
                                        Exit Do
                                    End If
                                    Dim intResponse2 As Integer
                                    If Integer.TryParse(strResponse2, intResponse2) Then
                                        If intResponse2 >= 0 And intResponse2 <= 17 Then
                                            Select Case intResponse2
                                                Case 0
                                                    qfQuery.ItemType.ItemTypeFilter = Enums.ItemTypeType.AllItems
                                                    qfQuery.ItemType.DesiredByFilter = SelectDesiredBy()
                                                    If (From i In ItemTypeFilter.DesiredByWithRole Where i = qfQuery.ItemType.DesiredByFilter).Count > 0 Then
                                                        qfQuery.ItemType.DesiredByRoleFilter = SelectDesiredByRole(qfQuery.ItemType.DesiredByFilter)
                                                    End If
                                                    qfQuery.ItemType.RequiredLevelMinFilter = SelectRequiredLevelMin()
                                                    qfQuery.ItemType.RequiredLevelMaxFilter = SelectRequiredLevelMax(qfQuery.ItemType.RequiredLevelMinFilter)
                                                    qfQuery.ItemType.RarityFilter = SelectRarity()
                                                    SelectAdvancedOptions(qfQuery.AdvancedOptions)
                                                Case 1
                                                    qfQuery.ItemType.ItemTypeFilter = Enums.ItemTypeType.Weapons
                                                    qfQuery.ItemType.DesiredByFilter = SelectDesiredBy()
                                                    If (From i In ItemTypeFilter.DesiredByWithRole Where i = qfQuery.ItemType.DesiredByFilter).Count > 0 Then
                                                        qfQuery.ItemType.DesiredByRoleFilter = SelectDesiredByRole(qfQuery.ItemType.DesiredByFilter)
                                                    End If
                                                    qfQuery.ItemType.WeaponSlotFilter = SelectWeaponSlot()
                                                    qfQuery.ItemType.WeaponTypeFilter = SelectWeaponType()
                                                    qfQuery.ItemType.RequiredLevelMinFilter = SelectRequiredLevelMin()
                                                    qfQuery.ItemType.RequiredLevelMaxFilter = SelectRequiredLevelMax(qfQuery.ItemType.RequiredLevelMinFilter)
                                                    qfQuery.ItemType.RarityFilter = SelectRarity()
                                                    SelectAdvancedOptions(qfQuery.AdvancedOptions)
                                                Case 2
                                                    qfQuery.ItemType.ItemTypeFilter = Enums.ItemTypeType.Armor
                                                    qfQuery.ItemType.DesiredByFilter = SelectDesiredBy()
                                                    If (From i In ItemTypeFilter.DesiredByWithRole Where i = qfQuery.ItemType.DesiredByFilter).Count > 0 Then
                                                        qfQuery.ItemType.DesiredByRoleFilter = SelectDesiredByRole(qfQuery.ItemType.DesiredByFilter)
                                                    End If
                                                    qfQuery.ItemType.ArmorSlotFilter = SelectArmorSlot()
                                                    qfQuery.ItemType.ArmorTypeFilter = SelectArmorType()
                                                    qfQuery.ItemType.RequiredLevelMinFilter = SelectRequiredLevelMin()
                                                    qfQuery.ItemType.RequiredLevelMaxFilter = SelectRequiredLevelMax(qfQuery.ItemType.RequiredLevelMinFilter)
                                                    qfQuery.ItemType.RarityFilter = SelectRarity()
                                                    SelectAdvancedOptions(qfQuery.AdvancedOptions)
                                                Case 3
                                                    qfQuery.ItemType.ItemTypeFilter = Enums.ItemTypeType.Gems
                                                    qfQuery.ItemType.RarityFilter = SelectRarity()
                                                    qfQuery.ItemType.GemTypeFilter = SelectGemType()
                                                    qfQuery.ItemType.DesiredByFilter = SelectDesiredBy()
                                                    If (From i In ItemTypeFilter.DesiredByWithRole Where i = qfQuery.ItemType.DesiredByFilter).Count > 0 Then
                                                        qfQuery.ItemType.DesiredByRoleFilter = SelectDesiredByRole(qfQuery.ItemType.DesiredByFilter)
                                                    End If
                                                    SelectAdvancedOptions(qfQuery.AdvancedOptions)
                                                Case 4
                                                    qfQuery.ItemType.ItemTypeFilter = Enums.ItemTypeType.Containers
                                                    qfQuery.ItemType.ContainerTypeFilter = SelectContainerType()
                                                Case 5
                                                    qfQuery.ItemType.ItemTypeFilter = Enums.ItemTypeType.Consumables
                                                    qfQuery.ItemType.RarityFilter = SelectRarity()
                                                Case 6
                                                    qfQuery.ItemType.ItemTypeFilter = Enums.ItemTypeType.TradeGoods
                                                    qfQuery.ItemType.RarityFilter = SelectRarity()
                                                Case 7
                                                    qfQuery.ItemType.ItemTypeFilter = Enums.ItemTypeType.Projectiles
                                                    qfQuery.ItemType.ProjectilesTypeFilter = SelectProjectilesType()
                                                    qfQuery.ItemType.RarityFilter = SelectRarity()
                                                Case 8
                                                    qfQuery.ItemType.ItemTypeFilter = Enums.ItemTypeType.Quivers
                                                    qfQuery.ItemType.QuiverTypeFilter = SelectQuiverType()
                                                Case 9
                                                    qfQuery.ItemType.ItemTypeFilter = Enums.ItemTypeType.Recipes
                                                    qfQuery.ItemType.RecipesTypeFilter = SelectRecipesType()
                                                    qfQuery.ItemType.RarityFilter = SelectRarity()
                                                    qfQuery.ItemType.SkillLevelMinFilter = SelectSkillLevelMin()
                                                    qfQuery.ItemType.SkillLevelMaxFilter = SelectSkillLevelMax(qfQuery.ItemType.SkillLevelMinFilter)
                                                Case 10
                                                    qfQuery.ItemType.ItemTypeFilter = Enums.ItemTypeType.Reagents
                                                    qfQuery.ItemType.RarityFilter = SelectRarity()
                                                Case 11
                                                    qfQuery.ItemType.ItemTypeFilter = Enums.ItemTypeType.Miscellaneous
                                                    qfQuery.ItemType.RarityFilter = SelectRarity()
                                                Case 12
                                                    qfQuery.ItemType.ItemTypeFilter = Enums.ItemTypeType.EnchantmentsPermanent
                                                    qfQuery.ItemType.PermanentEnchantmentSlotFilter = SelectPermanentEnchantmentSlot()
                                                    qfQuery.ItemType.RarityFilter = SelectRarity()
                                                    SelectAdvancedOptions(qfQuery.AdvancedOptions)
                                                Case 13
                                                    qfQuery.ItemType.ItemTypeFilter = Enums.ItemTypeType.EnchantmentsTemporary
                                                    qfQuery.ItemType.RarityFilter = SelectRarity()
                                                    SelectAdvancedOptions(qfQuery.AdvancedOptions)
                                                Case 14
                                                    qfQuery.ItemType.ItemTypeFilter = Enums.ItemTypeType.Mounts
                                                Case 15
                                                    qfQuery.ItemType.ItemTypeFilter = Enums.ItemTypeType.SmallPets
                                                Case 16
                                                    qfQuery.ItemType.ItemTypeFilter = Enums.ItemTypeType.Keys
                                                Case 17
                                                    qfQuery.ItemType.ItemTypeFilter = Enums.ItemTypeType.Glyphs
                                                    qfQuery.ItemType.DesiredByFilter = SelectDesiredBy()
                                                    If (From i In ItemTypeFilter.DesiredByWithRole Where i = qfQuery.ItemType.DesiredByFilter).Count > 0 Then
                                                        qfQuery.ItemType.DesiredByRoleFilter = SelectDesiredByRole(qfQuery.ItemType.DesiredByFilter)
                                                    End If
                                            End Select
                                            Console.Clear()
                                            Exit Do
                                        End If
                                    End If
                                    Console.Clear()
                                    Console.WriteLine("Invalid item type.  Please try again.")
                                    Console.WriteLine()
                                Loop
                            Case 3
                                Console.Clear()
                                Console.WriteLine("Search Terms")
                                Console.WriteLine()
                                Console.WriteLine("Enter your search terms:")

                                Console.Write(">")
                                qfQuery.SearchQuery = Console.ReadLine
                                Console.Clear()
                            Case 4
                                Exit Do
                        End Select
                    End If
                End If
            Loop

            ' Perform search
            Dim isSearch As New ItemSearch
            isSearch.Filter = qfQuery
            isSearch.Search()

            ' Return results
            Console.Clear()
            If isSearch.Items.Count = 0 Then
                Console.WriteLine("Your query did not produce any results.")
                Console.WriteLine()
            Else
                Console.WriteLine("Search Results")
                Console.WriteLine()
                For Each iItem As LibWowArmory.Item.Search.Item In isSearch.Items.OrderByDescending(Function(i) i.Relevance)
                    Console.WriteLine("{0}) {1}", iItem.ItemID, iItem.Name)
                Next
            End If
            Console.WriteLine("Press any key to continue.")
            Console.ReadKey(True)
        End Sub

        Private Function SelectDungeon(ByRef dDungeons As Dungeons) As String
            Console.Clear()
            Console.WriteLine("Dungeon Selection")
            Console.WriteLine()
            Do
                Console.WriteLine("Select a dungeon key")
                Console.WriteLine("  Or press enter to exit.")

                For Each dDungeon As LibWowArmory.Dungeon.Dungeon In dDungeons.Dungeons
                    Console.WriteLine("{0}) {1}", dDungeon.Key, dDungeon.Name)
                Next
                Console.WriteLine()
                Console.Write(">")

                Dim strResponse As String = Console.ReadLine
                If String.IsNullOrEmpty(strResponse) Then
                    Return "all"
                End If
                Dim varDungeons = (From d In dDungeons.Dungeons Where d.Key = strResponse)
                If varDungeons.Count > 0 Then
                    Return strResponse
                End If
                Console.Clear()
                Console.WriteLine("Invalid dungeon key.  Please try again.")
                Console.WriteLine()
            Loop
        End Function

        Private Function SelectBoss(ByVal dDungeon As LibWowArmory.Dungeon.Dungeon) As Integer
            Console.Clear()
            Console.WriteLine("Boss Selection")
            Console.WriteLine()
            Do
                Console.WriteLine("Select a boss ID")
                Console.WriteLine("  Or press enter to exit.")

                For Each bBoss As LibWowArmory.Dungeon.Boss In dDungeon.Bosses
                    Console.WriteLine("{0}) {1}", bBoss.BossID, bBoss.Name)
                Next
                Console.WriteLine()
                Console.Write(">")

                Dim strResponse As String = Console.ReadLine
                If String.IsNullOrEmpty(strResponse) Then Return 0
                Dim intResponse As Integer
                If Integer.TryParse(strResponse, intResponse) Then
                    Dim varBosses = (From b In dDungeon.Bosses Where b.BossID = strResponse)
                    If varBosses.Count > 0 Then
                        Return varBosses.First.BossID
                    End If
                End If
                Console.Clear()
                Console.WriteLine("Invalid boss ID.  Please try again.")
                Console.WriteLine()
            Loop
        End Function

        Private Function SelectDifficulty() As Enums.DifficultyType
            Console.Clear()
            Console.WriteLine("Dungeon Difficulty Selection")
            Console.WriteLine()
            Do
                Console.WriteLine("Select a dungeon difficulty")

                Console.WriteLine("0) Normal & Heroic")
                Console.WriteLine("1) Normal Only")
                Console.WriteLine("2) Heroic Only")

                Console.WriteLine()
                Console.Write(">")
                Dim ckiKey As ConsoleKeyInfo = Console.ReadKey
                Console.WriteLine()

                Dim intKey As Integer
                If Integer.TryParse(ckiKey.KeyChar, intKey) Then
                    If intKey >= 0 And intKey <= 2 Then
                        Return CType(intKey, Enums.DifficultyType)
                    End If
                End If
                Console.Clear()
                Console.WriteLine("Invalid difficulty.  Please try again.")
                Console.WriteLine()
            Loop
        End Function

        Private Function SelectFaction(ByVal fFactions As Factions) As Integer
            Console.Clear()
            Console.WriteLine("Reputation Faction Selection")
            Console.WriteLine()
            Do
                Console.WriteLine("Select a faction ID")
                Console.WriteLine("  Or press enter to exit.")

                Console.WriteLine("0) All Factions")
                For Each fFaction As Faction In fFactions.Factions
                    Console.WriteLine("{0}) {1}", fFaction.FactionID, fFaction.Name)
                Next
                Console.WriteLine()
                Console.Write(">")

                Dim strResponse As String = Console.ReadLine
                If String.IsNullOrEmpty(strResponse) Then Return 0
                Dim intResponse As Integer
                If Integer.TryParse(strResponse, intResponse) Then
                    If intResponse = 0 OrElse (From f In fFactions.Factions Where f.FactionID = intResponse).Count > 0 Then
                        Return intResponse
                    End If
                End If
                Console.Clear()
                Console.WriteLine("Invalid faction ID.  Please try again.")
                Console.WriteLine()
            Loop
        End Function

        Private Function SelectPvpAllianceSource() As Enums.PvpAllianceSourceType
            Console.Clear()
            Console.WriteLine("Alliance PvP Selection")
            Console.WriteLine()
            Do
                Console.WriteLine("Select a PvP source")
                Console.WriteLine("  Or press enter to exit.")

                Console.WriteLine("0) All Pvp Sources")
                Console.WriteLine("1) Wintergrasp")
                Console.WriteLine("2) Arena Season 6")
                Console.WriteLine("3) Arena Season 5")
                Console.WriteLine("4) Arena Season 4")
                Console.WriteLine("5) Honor Rewards")
                Console.WriteLine("6) Arathi Basin")
                Console.WriteLine("7) Alterac Valley")
                Console.WriteLine("8) Warsong Gulch")
                Console.WriteLine("9) Halaa")
                Console.WriteLine("10) Honor Hold")
                Console.WriteLine("11) Terokkar")
                Console.WriteLine("12) Zangarmarsh")

                Console.WriteLine()
                Console.Write(">")

                Dim strResponse As String = Console.ReadLine
                If String.IsNullOrEmpty(strResponse) Then Return 0
                Dim intResponse As Integer
                If Integer.TryParse(strResponse, intResponse) Then
                    If intResponse >= 0 And intResponse <= 12 Then
                        Return CType(intResponse, Enums.PvpAllianceSourceType)
                    End If
                End If
                Console.Clear()
                Console.WriteLine("Invalid source.  Please try again.")
                Console.WriteLine()
            Loop
        End Function

        Private Function SelectPvpHordeSource() As Enums.PvpHordeSourceType
            Console.Clear()
            Console.WriteLine("Horde PvP Selection")
            Console.WriteLine()
            Do
                Console.WriteLine("Select a PvP source")
                Console.WriteLine("  Or press enter to exit.")

                Console.WriteLine("0) All Pvp Sources")
                Console.WriteLine("1) Wintergrasp")
                Console.WriteLine("2) Arena Season 6")
                Console.WriteLine("3) Arena Season 5")
                Console.WriteLine("4) Arena Season 4")
                Console.WriteLine("5) Honor Rewards")
                Console.WriteLine("6) Arathi Basin")
                Console.WriteLine("7) Alterac Valley")
                Console.WriteLine("8) Warsong Gulch")
                Console.WriteLine("9) Halaa")
                Console.WriteLine("10) Thrallmar")
                Console.WriteLine("11) Terokkar")
                Console.WriteLine("12) Zangarmarsh")

                Console.WriteLine()
                Console.Write(">")

                Dim strResponse As String = Console.ReadLine
                If String.IsNullOrEmpty(strResponse) Then Return 0
                Dim intResponse As Integer
                If Integer.TryParse(strResponse, intResponse) Then
                    If intResponse >= 0 And intResponse <= 12 Then
                        Return CType(intResponse, Enums.PvpHordeSourceType)
                    End If
                End If
                Console.Clear()
                Console.WriteLine("Invalid source.  Please try again.")
                Console.WriteLine()
            Loop
        End Function

        Private Function SelectDesiredBy() As Enums.DesiredByType
            Console.Clear()
            Console.WriteLine("Desired By Selection")
            Console.WriteLine()
            Do
                Console.WriteLine("Select a desired class")

                Console.WriteLine("0) Any Class")
                Console.WriteLine("6) Death Knight")
                Console.WriteLine("11) Druid")
                Console.WriteLine("3) Hunter")
                Console.WriteLine("8) Mage")
                Console.WriteLine("2) Paladin")
                Console.WriteLine("5) Priest")
                Console.WriteLine("4) Rogue")
                Console.WriteLine("7) Shaman")
                Console.WriteLine("9) Warlock")
                Console.WriteLine("1) Warrior")

                Console.WriteLine()
                Console.Write(">")

                Dim strResponse As String = Console.ReadLine
                If String.IsNullOrEmpty(strResponse) Then Return 0
                Dim intResponse As Integer
                If Integer.TryParse(strResponse, intResponse) Then
                    If intResponse >= 0 And intResponse <= 11 And intResponse <> 10 Then
                        Return CType(intResponse, Enums.DesiredByType)
                    End If
                End If
                Console.Clear()
                Console.WriteLine("Invalid desired by class.  Please try again.")
                Console.WriteLine()
            Loop
        End Function

        Private Function SelectDesiredByRole(ByVal dbClass As Enums.DesiredByType) As Enums.DesiredByRoleType
            Console.Clear()
            Console.WriteLine("Desired By Role Selection")
            Console.WriteLine()
            Do
                Dim cArray As New Collection(Of Integer)

                Console.WriteLine("Select a desired role")

                Console.WriteLine("0) Any Type")
                cArray.Add(0)
                If (From i In ItemTypeFilter.DesiredByWithRoleTank Where i = dbClass).Count > 0 Then
                    Console.WriteLine("1) Tank")
                    cArray.Add(1)
                End If
                If (From i In ItemTypeFilter.DesiredByWithRoleMeleeDPS Where i = dbClass).Count > 0 Then
                    Console.WriteLine("2) Melee DPS")
                    cArray.Add(2)
                End If
                If (From i In ItemTypeFilter.DesiredByWithRoleCasterDPS Where i = dbClass).Count > 0 Then
                    Console.WriteLine("3) Caster DPS")
                    cArray.Add(3)
                End If
                If (From i In ItemTypeFilter.DesiredByWithRoleHealer Where i = dbClass).Count > 0 Then
                    Console.WriteLine("4) Healer")
                    cArray.Add(4)
                End If
                If (From i In ItemTypeFilter.DesiredByWithRolePlusDamageOnly Where i = dbClass).Count > 0 Then
                    Console.WriteLine("5) +Damage Only")
                    cArray.Add(5)
                End If
                If (From i In ItemTypeFilter.DesiredByWithRolePlusDamageAndCrit Where i = dbClass).Count > 0 Then
                    Console.WriteLine("6) +Damage & Crit")
                    cArray.Add(6)
                End If

                Console.WriteLine()
                Console.Write(">")

                Dim strResponse As String = Console.ReadLine
                If String.IsNullOrEmpty(strResponse) Then Return 0
                Dim intResponse As Integer
                If Integer.TryParse(strResponse, intResponse) Then
                    If (From i In cArray Where i = intResponse).Count > 0 Then
                        Return CType(intResponse, Enums.DesiredByRoleType)
                    End If
                End If
                Console.Clear()
                Console.WriteLine("Invalid desired by role.  Please try again.")
                Console.WriteLine()
            Loop
        End Function

        Private Function SelectWeaponSlot() As Enums.WeaponSlotType
            Console.Clear()
            Console.WriteLine("Weapon Slot Selection")
            Console.WriteLine()
            Do
                Console.WriteLine("Select a weapon slot")

                Console.WriteLine("0) All Slots")
                Console.WriteLine("1) Main Hand")
                Console.WriteLine("2) Off Hand")
                Console.WriteLine("3) Main or Off Hand")
                Console.WriteLine("4) Two Handed")
                Console.WriteLine("5) Ranged")

                Console.WriteLine()
                Console.Write(">")

                Dim strResponse As String = Console.ReadLine
                If String.IsNullOrEmpty(strResponse) Then Return 0
                Dim intResponse As Integer
                If Integer.TryParse(strResponse, intResponse) Then
                    If intResponse >= 0 And intResponse <= 5 Then
                        Return CType(intResponse, Enums.WeaponSlotType)
                    End If
                End If
                Console.Clear()
                Console.WriteLine("Invalid weapon slot.  Please try again.")
                Console.WriteLine()
            Loop
        End Function

        Private Function SelectWeaponType() As Enums.WeaponTypeType
            Console.Clear()
            Console.WriteLine("Weapon Type Selection")
            Console.WriteLine()
            Do
                Console.WriteLine("Select a weapon type")

                Console.WriteLine("0) All Weapon Types")
                Console.WriteLine("1) One Handed Axes")
                Console.WriteLine("2) Two Handed Axes")
                Console.WriteLine("3) Bows")
                Console.WriteLine("4) Guns")
                Console.WriteLine("5) One Handed Maces")
                Console.WriteLine("6) Two Handed Maces")
                Console.WriteLine("7) Polearms")
                Console.WriteLine("8) One Handed Swords")
                Console.WriteLine("9) Two Handed Swords")
                Console.WriteLine("10) Fist Weapons")
                Console.WriteLine("11) Miscellaneous")
                Console.WriteLine("12) Daggers")
                Console.WriteLine("13) Thrown")
                Console.WriteLine("14) Crossbows")
                Console.WriteLine("15) Wands")
                Console.WriteLine("16) Fishing Pole")

                Console.WriteLine()
                Console.Write(">")

                Dim strResponse As String = Console.ReadLine
                If String.IsNullOrEmpty(strResponse) Then Return 0
                Dim intResponse As Integer
                If Integer.TryParse(strResponse, intResponse) Then
                    If intResponse >= 0 And intResponse <= 16 Then
                        Return CType(intResponse, Enums.WeaponTypeType)
                    End If
                End If
                Console.Clear()
                Console.WriteLine("Invalid weapon type.  Please try again.")
                Console.WriteLine()
            Loop
        End Function

        Function SelectRequiredLevelMin() As Integer
            Console.Clear()
            Console.WriteLine("Minimum Required Level")
            Console.WriteLine()
            Do
                Console.WriteLine("Enter the minimum required level")
                Console.WriteLine("  or press enter to exit")

                Console.WriteLine()
                Console.Write(">")

                Dim strResponse As String = Console.ReadLine
                If String.IsNullOrEmpty(strResponse) Then Return 0
                Dim intResponse As Integer
                If Integer.TryParse(strResponse, intResponse) Then
                    If intResponse >= 1 And intResponse <= 80 Then
                        Return intResponse
                    End If
                End If
                Console.Clear()
                Console.WriteLine("The level must be between 1 and 80.")
                Console.WriteLine()
            Loop
        End Function

        Function SelectRequiredLevelMax(ByVal intRequiredLevelMin As Integer) As Integer
            Console.Clear()
            Console.WriteLine("Maximum Required Level")
            Console.WriteLine()
            Do
                Console.WriteLine("Enter the maximum required level")
                Console.WriteLine("  or press enter to exit")

                Console.WriteLine()
                Console.Write(">")

                Dim strResponse As String = Console.ReadLine
                If String.IsNullOrEmpty(strResponse) Then Return 0
                Dim intResponse As Integer
                If Integer.TryParse(strResponse, intResponse) Then
                    If intResponse >= 1 And intResponse <= 80 Then
                        If intRequiredLevelMin = 0 Or intResponse >= intRequiredLevelMin Then
                            Return intResponse
                        End If
                    End If
                End If
                Console.Clear()
                Console.WriteLine("The level must be between {0} and 80.", If(intRequiredLevelMin = 0, 1, intRequiredLevelMin))
                Console.WriteLine()
            Loop
        End Function

        Private Function SelectRarity() As Enums.RarityType
            Console.Clear()
            Console.WriteLine("Rarity Selection")
            Console.WriteLine()
            Do
                Console.WriteLine("Select a minimum rarity")
                Console.WriteLine("  or press enter to exit")

                Console.WriteLine("0) Poor")
                Console.WriteLine("1) Common")
                Console.WriteLine("2) Uncommon")
                Console.WriteLine("3) Rare")
                Console.WriteLine("4) Epic")
                Console.WriteLine("5) Legendary")
                Console.WriteLine("6) Heirloom")

                Console.WriteLine()
                Console.Write(">")

                Dim strResponse As String = Console.ReadLine
                If String.IsNullOrEmpty(strResponse) Then Return -1
                Dim intResponse As Integer
                If Integer.TryParse(strResponse, intResponse) Then
                    If intResponse >= 0 And intResponse <= 6 Then
                        Return CType(intResponse, Enums.RarityType)
                    End If
                End If
                Console.Clear()
                Console.WriteLine("Invalid rarity.  Please try again.")
                Console.WriteLine()
            Loop
        End Function

        Private Function SelectArmorSlot() As Enums.ArmorSlotType
            Console.Clear()
            Console.WriteLine("Armor Slot Selection")
            Console.WriteLine()
            Do
                Console.WriteLine("Select an armor slot")

                Console.WriteLine("0) All Slots")
                Console.WriteLine("1) Head")
                Console.WriteLine("2) Neck")
                Console.WriteLine("3) Shoulders")
                Console.WriteLine("4) Back")
                Console.WriteLine("5) Chest")
                Console.WriteLine("6) Shirt")
                Console.WriteLine("7) Wrists")
                Console.WriteLine("8) Hands")
                Console.WriteLine("9) Waist")
                Console.WriteLine("10) Legs")
                Console.WriteLine("11) Feet")
                Console.WriteLine("12) Finger")
                Console.WriteLine("13) Trinket")
                Console.WriteLine("14) Off Hand Frill")

                Console.WriteLine()
                Console.Write(">")

                Dim strResponse As String = Console.ReadLine
                If String.IsNullOrEmpty(strResponse) Then Return 0
                Dim intResponse As Integer
                If Integer.TryParse(strResponse, intResponse) Then
                    If intResponse >= 0 And intResponse <= 14 Then
                        Return CType(intResponse, Enums.ArmorSlotType)
                    End If
                End If
                Console.Clear()
                Console.WriteLine("Invalid armor slot.  Please try again.")
                Console.WriteLine()
            Loop
        End Function

        Private Function SelectArmorType() As Enums.ArmorTypeType
            Console.Clear()
            Console.WriteLine("Armor Type Selection")
            Console.WriteLine()
            Do
                Console.WriteLine("Select an armor type")

                Console.WriteLine("0) All Armor Types")
                Console.WriteLine("1) Cloth")
                Console.WriteLine("2) Leather")
                Console.WriteLine("3) Mail")
                Console.WriteLine("4) Plate")
                Console.WriteLine("5) Shield")
                Console.WriteLine("6) Idol")
                Console.WriteLine("7) Libram")
                Console.WriteLine("8) Totem")
                Console.WriteLine("9) Sigil")
                Console.WriteLine("10) Miscellaneous")

                Console.WriteLine()
                Console.Write(">")

                Dim strResponse As String = Console.ReadLine
                If String.IsNullOrEmpty(strResponse) Then Return 0
                Dim intResponse As Integer
                If Integer.TryParse(strResponse, intResponse) Then
                    If intResponse >= 0 And intResponse <= 10 Then
                        Return CType(intResponse, Enums.ArmorTypeType)
                    End If
                End If
                Console.Clear()
                Console.WriteLine("Invalid armor type.  Please try again.")
                Console.WriteLine()
            Loop
        End Function

        Private Function SelectGemType() As Enums.GemTypeType
            Console.Clear()
            Console.WriteLine("Gem Type Selection")
            Console.WriteLine()
            Do
                Console.WriteLine("Select a gem type")

                Console.WriteLine("0) All Gem Types")
                Console.WriteLine("1) Blue")
                Console.WriteLine("2) Red")
                Console.WriteLine("3) Yellow")
                Console.WriteLine("4) Meta")
                Console.WriteLine("5) Green")
                Console.WriteLine("6) Orange")
                Console.WriteLine("7) Purple")
                Console.WriteLine("8) Prismatic")

                Console.WriteLine()
                Console.Write(">")

                Dim strResponse As String = Console.ReadLine
                If String.IsNullOrEmpty(strResponse) Then Return 0
                Dim intResponse As Integer
                If Integer.TryParse(strResponse, intResponse) Then
                    If intResponse >= 0 And intResponse <= 8 Then
                        Return CType(intResponse, Enums.ArmorTypeType)
                    End If
                End If
                Console.Clear()
                Console.WriteLine("Invalid gem type.  Please try again.")
                Console.WriteLine()
            Loop
        End Function

        Private Function SelectContainerType() As Enums.BagTypeType
            Console.Clear()
            Console.WriteLine("Bag Type Selection")
            Console.WriteLine()
            Do
                Console.WriteLine("Select a bag type")

                Console.WriteLine("0) All Bags")
                Console.WriteLine("1) Bag")
                Console.WriteLine("2) Soul Bag")
                Console.WriteLine("3) Herb Bag")
                Console.WriteLine("4) Enchanting Bag")
                Console.WriteLine("5) Engineering Bag")
                Console.WriteLine("6) Gem Bag")
                Console.WriteLine("7) Mining Bag")

                Console.WriteLine()
                Console.Write(">")

                Dim strResponse As String = Console.ReadLine
                If String.IsNullOrEmpty(strResponse) Then Return 0
                Dim intResponse As Integer
                If Integer.TryParse(strResponse, intResponse) Then
                    If intResponse >= 0 And intResponse <= 7 Then
                        Return CType(intResponse, Enums.BagTypeType)
                    End If
                End If
                Console.Clear()
                Console.WriteLine("Invalid bag type.  Please try again.")
                Console.WriteLine()
            Loop
        End Function

        Private Function SelectProjectilesType() As Enums.ProjectileTypeType
            Console.Clear()
            Console.WriteLine("Projectile Type Selection")
            Console.WriteLine()
            Do
                Console.WriteLine("Select a projectile type")

                Console.WriteLine("0) All Projectiles")
                Console.WriteLine("1) Arrow")
                Console.WriteLine("2) Bullet")

                Console.WriteLine()
                Console.Write(">")

                Dim strResponse As String = Console.ReadLine
                If String.IsNullOrEmpty(strResponse) Then Return 0
                Dim intResponse As Integer
                If Integer.TryParse(strResponse, intResponse) Then
                    If intResponse >= 0 And intResponse <= 2 Then
                        Return CType(intResponse, Enums.ProjectileTypeType)
                    End If
                End If
                Console.Clear()
                Console.WriteLine("Invalid projectile type.  Please try again.")
                Console.WriteLine()
            Loop
        End Function

        Private Function SelectQuiverType() As Enums.QuiverTypeType
            Console.Clear()
            Console.WriteLine("Quiver Type Selection")
            Console.WriteLine()
            Do
                Console.WriteLine("Select a quiver type")

                Console.WriteLine("0) All Quivers")
                Console.WriteLine("1) Quiver")
                Console.WriteLine("2) Ammo Pouch")

                Console.WriteLine()
                Console.Write(">")

                Dim strResponse As String = Console.ReadLine
                If String.IsNullOrEmpty(strResponse) Then Return 0
                Dim intResponse As Integer
                If Integer.TryParse(strResponse, intResponse) Then
                    If intResponse >= 0 And intResponse <= 2 Then
                        Return CType(intResponse, Enums.QuiverTypeType)
                    End If
                End If
                Console.Clear()
                Console.WriteLine("Invalid quiver type.  Please try again.")
                Console.WriteLine()
            Loop
        End Function

        Private Function SelectRecipesType() As Enums.RecipesTypeType
            Console.Clear()
            Console.WriteLine("Recipe Type Selection")
            Console.WriteLine()
            Do
                Console.WriteLine("Select a recipe type")

                Console.WriteLine("0) All Recipes")
                Console.WriteLine("1) Books")
                Console.WriteLine("2) Leatherworking")
                Console.WriteLine("3) Tailoring")
                Console.WriteLine("4) Engineering")
                Console.WriteLine("5) Blacksmithing")
                Console.WriteLine("6) Cooking")
                Console.WriteLine("7) Alchemy")
                Console.WriteLine("8) First Aid")
                Console.WriteLine("9) Enchanting")
                Console.WriteLine("10) Fishing")
                Console.WriteLine("11) Jewelcrafting")

                Console.WriteLine()
                Console.Write(">")

                Dim strResponse As String = Console.ReadLine
                If String.IsNullOrEmpty(strResponse) Then Return 0
                Dim intResponse As Integer
                If Integer.TryParse(strResponse, intResponse) Then
                    If intResponse >= 0 And intResponse <= 11 Then
                        Return CType(intResponse, Enums.RecipesTypeType)
                    End If
                End If
                Console.Clear()
                Console.WriteLine("Invalid recipe type.  Please try again.")
                Console.WriteLine()
            Loop
        End Function

        Function SelectSkillLevelMin() As Integer
            Console.Clear()
            Console.WriteLine("Minimum Skill Level")
            Console.WriteLine()
            Do
                Console.WriteLine("Enter the minimum skill level")
                Console.WriteLine("  or press enter to exit")

                Console.WriteLine()
                Console.Write(">")

                Dim strResponse As String = Console.ReadLine
                If String.IsNullOrEmpty(strResponse) Then Return 0
                Dim intResponse As Integer
                If Integer.TryParse(strResponse, intResponse) Then
                    If intResponse >= 1 And intResponse <= 450 Then
                        Return intResponse
                    End If
                End If
                Console.Clear()
                Console.WriteLine("The level must be between 1 and 450.")
                Console.WriteLine()
            Loop
        End Function

        Function SelectSkillLevelMax(ByVal intSkillLevelMin As Integer) As Integer
            Console.Clear()
            Console.WriteLine("Maximum Skill Level")
            Console.WriteLine()
            Do
                Console.WriteLine("Enter the maximum skill level")
                Console.WriteLine("  or press enter to exit")

                Console.WriteLine()
                Console.Write(">")

                Dim strResponse As String = Console.ReadLine
                If String.IsNullOrEmpty(strResponse) Then Return 0
                Dim intResponse As Integer
                If Integer.TryParse(strResponse, intResponse) Then
                    If intResponse >= 1 And intResponse <= 450 Then
                        If intSkillLevelMin = 0 Or intResponse >= intSkillLevelMin Then
                            Return intResponse
                        End If
                    End If
                End If
                Console.Clear()
                Console.WriteLine("The level must be between {0} and 450.", If(intSkillLevelMin = 0, 1, intSkillLevelMin))
                Console.WriteLine()
            Loop
        End Function

        Private Function SelectPermanentEnchantmentSlot() As Enums.PermanentEnchantmentSlotType
            Console.Clear()
            Console.WriteLine("Permanent Enchantment Slot Selection")
            Console.WriteLine()
            Do
                Console.WriteLine("Select a permanent enchantment slot")

                Console.WriteLine("0) All Slots")
                Console.WriteLine("1) Head")
                Console.WriteLine("3) Shoulders")
                Console.WriteLine("4) Back")
                Console.WriteLine("5) Chest")
                Console.WriteLine("7) Wrists")
                Console.WriteLine("8) Hands")
                Console.WriteLine("10) Legs")
                Console.WriteLine("11) Feet")
                Console.WriteLine("12) Finger")
                Console.WriteLine("15) Weapon")
                Console.WriteLine("16) Shield")

                Console.WriteLine()
                Console.Write(">")

                Dim strResponse As String = Console.ReadLine
                If String.IsNullOrEmpty(strResponse) Then Return 0
                Dim intResponse As Integer
                If Integer.TryParse(strResponse, intResponse) Then
                    If intResponse >= 0 And intResponse <= 16 And intResponse <> 2 And intResponse <> 6 And intResponse <> 9 And intResponse <> 13 And intResponse <> 14 Then
                        Return CType(intResponse, Enums.RecipesTypeType)
                    End If
                End If
                Console.Clear()
                Console.WriteLine("Invalid permanent enchantment slot.  Please try again.")
                Console.WriteLine()
            Loop
        End Function

        Private Sub SelectAdvancedOptions(ByVal aofFilters As Collection(Of AdvancedOptionsFilter))
            Console.Clear()
            Console.WriteLine("Advanced Options Filter Selection")
            Console.WriteLine()

            Do
                Console.WriteLine("Select a filter to delete it")
                Console.WriteLine("  or press enter to accept the current filters")
                Console.WriteLine("  or type ""add"" to add a new filter")

                Dim intCount As Integer = 0
                For Each aofFilter In aofFilters
                    intCount += 1
                    If aofFilter.AdvancedOptionsFilter <= Enums.AdvancedOptionsType.General_HitRating Then
                        Dim strOperator As String = ""
                        Select Case aofFilter.OperatorFilter
                            Case Enums.AdvancedOptionsOperatorType.EqualTo
                                strOperator = "="
                            Case Enums.AdvancedOptionsOperatorType.GreaterThan
                                strOperator = ">"
                            Case Enums.AdvancedOptionsOperatorType.GreaterThanEqualTo
                                strOperator = ">="
                            Case Enums.AdvancedOptionsOperatorType.LessThan
                                strOperator = "<"
                            Case Enums.AdvancedOptionsOperatorType.LessThanEqualTo
                                strOperator = "<="
                        End Select
                        Console.WriteLine("{0}) {1} {2} {3}", intCount, [Enum].GetName(GetType(Enums.AdvancedOptionsType), aofFilter.AdvancedOptionsFilter), strOperator, aofFilter.RangeFilter)
                    Else
                        Console.WriteLine("{0}) {1}", intCount, [Enum].GetName(GetType(Enums.AdvancedOptionsType), aofFilter.AdvancedOptionsFilter))
                    End If
                Next
                Console.WriteLine()

                Console.Write(">")
                Dim strResponse As String = Console.ReadLine
                If String.IsNullOrEmpty(strResponse) Then Exit Sub
                Dim intResponse As Integer
                If Integer.TryParse(strResponse, intResponse) Then
                    If intResponse >= 1 And intResponse <= intCount Then
                        aofFilters.RemoveAt(intResponse - 1)
                        Console.Clear()
                        Continue Do
                    End If
                ElseIf strResponse.ToUpperInvariant = "ADD" Then
                    Dim aofFilter As AdvancedOptionsFilter = SelectAdvancedFilter()
                    If aofFilter IsNot Nothing Then aofFilters.Add(aofFilter)
                    Console.Clear()
                    Continue Do
                End If
                Console.Clear()
                Console.WriteLine("Invalid filter.  Please try again.")
                Console.WriteLine()
            Loop
        End Sub

        Private Function SelectAdvancedFilter() As AdvancedOptionsFilter
            Console.Clear()
            Console.WriteLine("Advanced Options Filter Selection")
            Console.WriteLine()
            Do
                Console.WriteLine("Select an advanced option")
                Console.WriteLine("  Or press enter to exit")
                Console.WriteLine()
                Console.WriteLine("Base Stat Bonuses")
                Console.WriteLine("0) Strength")
                Console.WriteLine("1) Agility")
                Console.WriteLine("2) Stamina")
                Console.WriteLine("3) Intellect")
                Console.WriteLine("4) Spirit")
                Console.WriteLine()
                Console.WriteLine("General Bonuses")
                Console.WriteLine("5) Crit Rating")
                Console.WriteLine("6) Hit Rating")
                Console.WriteLine("7) Haste Rating")
                Console.WriteLine()
                Console.WriteLine("Physical Combat Bonsues")
                Console.WriteLine("8) Attack Power")
                Console.WriteLine("9) Feral Attack Power")
                Console.WriteLine("10) Armor Penetration")
                Console.WriteLine("11) Expertise Rating")
                Console.WriteLine()
                Console.WriteLine("Spell Bonuses")
                Console.WriteLine("12) Spell Power")
                Console.WriteLine("13) Spell Crit Rating")
                Console.WriteLine("14) Spell Hit Rating")
                Console.WriteLine("15) Penetration")
                Console.WriteLine("16) Mana Regen")
                Console.WriteLine("17) Spell Haste Rating")
                Console.WriteLine("18) Arcane Damage")
                Console.WriteLine("19) Holy Damage")
                Console.WriteLine("20) Shadow Damage")
                Console.WriteLine("21) Nature Damage")
                Console.WriteLine("22) Frost Damage")
                Console.WriteLine("23) Fire Damage")
                Console.WriteLine()
                Console.WriteLine("Defense Bonuses")
                Console.WriteLine("24) Armor")
                Console.WriteLine("25) Block Rating")
                Console.WriteLine("26) Block Value")
                Console.WriteLine("27) Defense Rating")
                Console.WriteLine("28) Dodge Rating")
                Console.WriteLine("29) Parry Rating")
                Console.WriteLine("30) Health Regen")
                Console.WriteLine("31) Resilience")
                Console.WriteLine()
                Console.WriteLine("Resistance Bonuses")
                Console.WriteLine("32) Arcane Resist")
                Console.WriteLine("33) Shadow Resist")
                Console.WriteLine("34) Nature Resist")
                Console.WriteLine("35) Frost Resist")
                Console.WriteLine("36) Fire Resist")
                Console.WriteLine()
                Console.WriteLine("Weapon Stats")
                Console.WriteLine("37) DPS")
                Console.WriteLine("38) Min Damage")
                Console.WriteLine("39) Max Damage")
                Console.WriteLine("40) Speed")
                Console.WriteLine()
                Console.WriteLine("General Bonuses")
                Console.WriteLine("41) Bind on Pickup")
                Console.WriteLine("42) Bind on Equip")
                Console.WriteLine("43) Bind on Use")
                Console.WriteLine("44) Unique")
                Console.WriteLine("45) Unique Equipped")
                Console.WriteLine()
                Console.WriteLine("Has Spell Effect")
                Console.WriteLine("46) Chance to Resist")
                Console.WriteLine("47) Avoid Interruption")
                Console.WriteLine("48) Chance on Hit or Cast")
                Console.WriteLine("49) Dispel Effects")
                Console.WriteLine("50) Reduce Cooldown")
                Console.WriteLine("51) Reduce Cast Time")
                Console.WriteLine("52) Reduce Spell Cost")
                Console.WriteLine("53) Increase Duration")
                Console.WriteLine("54) Increase Range")
                Console.WriteLine("55) Reduce Threat")
                Console.WriteLine("56) Group Buff")
                Console.WriteLine("57) Summon Creature")
                Console.WriteLine()

                Console.Write(">")
                Dim strResponse As String = Console.ReadLine
                If String.IsNullOrEmpty(strResponse) Then Return Nothing
                Dim intResponse As Integer
                If Integer.TryParse(strResponse, intResponse) Then
                    If intResponse >= 0 And intResponse <= 40 Then
                        Dim aofFilter As New AdvancedOptionsFilter
                        aofFilter.AdvancedOptionsFilter = CType(intResponse, Enums.AdvancedOptionsType)
                        aofFilter.OperatorFilter = SelectAdvancedFilterOperator()
                        aofFilter.RangeFilter = SelectAdvancedFilterRange()
                        Return aofFilter
                    ElseIf intResponse >= 41 And intResponse <= 57 Then
                        Dim aofFilter As New AdvancedOptionsFilter
                        aofFilter.AdvancedOptionsFilter = CType(intResponse, Enums.AdvancedOptionsType)
                        Return aofFilter
                    End If
                End If
                Console.Clear()
                Console.WriteLine("Invalid gem type.  Please try again.")
                Console.WriteLine()
            Loop
        End Function

        Private Function SelectAdvancedFilterOperator() As Enums.AdvancedOptionsOperatorType
            Console.Clear()
            Console.WriteLine("Advanced Options Filter Operator Selection")
            Console.WriteLine()
            Do
                Console.WriteLine("Select an operator")
                Console.WriteLine()
                Console.WriteLine("0) >")
                Console.WriteLine("1) >=")
                Console.WriteLine("2) =")
                Console.WriteLine("3) <")
                Console.WriteLine("4) <=")
                Console.WriteLine()

                Console.Write(">")
                Dim strResponse As String = Console.ReadLine
                Dim intResponse As Integer
                If Integer.TryParse(strResponse, intResponse) Then
                    If intResponse >= 0 And intResponse <= 4 Then
                        Return CType(intResponse, Enums.AdvancedOptionsOperatorType)
                    End If
                End If
                Console.Clear()
                Console.WriteLine("Invalid operator.  Please try again.")
                Console.WriteLine()
            Loop
        End Function

        Private Function SelectAdvancedFilterRange() As Integer
            Console.Clear()
            Console.WriteLine("Advanced Options Filter Range Selection")
            Console.WriteLine()
            Do
                Console.WriteLine("Enter a range value to compare to")

                Console.Write(">")
                Dim strResponse As String = Console.ReadLine
                Dim intResponse As Integer
                If Integer.TryParse(strResponse, intResponse) Then
                    Return intResponse
                End If
                Console.Clear()
                Console.WriteLine("You must enter a value.")
                Console.WriteLine()
            Loop
        End Function

        Private Sub ItemTooltipDemo()
            Console.Clear()
            Console.WriteLine("Item Tooltip Demo")
            Console.WriteLine()

            Dim intItemID As Integer

            ' Get the item number
            Do
                Console.WriteLine("Please enter the ID number of the item you wish to lookup.")
                Console.Write(">")
                Dim strItemID As Integer = Console.ReadLine

                If String.IsNullOrEmpty(strItemID) Then
                    Console.WriteLine("You must enter an item number.")
                    Console.WriteLine()
                ElseIf Not Integer.TryParse(strItemID, intItemID) Then
                    Console.WriteLine("You must enter an item number.")
                    Console.WriteLine()
                Else
                    Exit Do
                End If
            Loop

            Dim itItemTooltip As New ItemTooltip(intItemID)

            ' Display the item's information
            Console.Clear()
            Console.WriteLine("{0} - {1}", itItemTooltip.Name, [Enum].GetName(GetType(Enums.RarityType), itItemTooltip.Quality))

            If itItemTooltip.Heroic Then
                Console.WriteLine("Heroic")
            End If

            If itItemTooltip.Conjured Then
                Console.WriteLine("Conjured")
            End If

            Select Case itItemTooltip.Bonding
                Case Enums.BondingType.BindOnEquip
                    Console.WriteLine("Binds when equipped")
                Case Enums.BondingType.BindOnPickup
                    Console.WriteLine("Binds when picked up")
                Case Enums.BondingType.BindOnUse
                    Console.WriteLine("Binds when used")
                Case Enums.BondingType.OtherQuestItem, Enums.BondingType.QuestItem
                    Console.WriteLine("Quest Item")
            End Select

            If itItemTooltip.AccountBound Then
                Console.WriteLine("Bound to account")
            End If

            If Not String.IsNullOrEmpty(itItemTooltip.InstanceBound) Then
                Console.WriteLine(itItemTooltip.InstanceBound)
            End If

            If Not String.IsNullOrEmpty(itItemTooltip.ZoneBound) Then
                Console.WriteLine(itItemTooltip.ZoneBound)
            End If

            If itItemTooltip.UniqueEquippable Then
                If itItemTooltip.MaxCount = 1 Then
                    Console.WriteLine("Unique-Equippable")
                Else
                    Console.WriteLine("Unique-Equippable ({0})", itItemTooltip.MaxCount)
                End If
            End If

            If itItemTooltip.MaxCount > 0 And Not itItemTooltip.UniqueEquippable Then
                If itItemTooltip.MaxCount = 1 Then
                    Console.WriteLine("Unique")
                Else
                    Console.WriteLine("Unique ({0})", itItemTooltip.MaxCount)
                End If
            End If

            If itItemTooltip.ContainerSlots > 0 Then
                If String.IsNullOrEmpty(itItemTooltip.Subclass) Then
                    Console.WriteLine("{0} Slot Bag", itItemTooltip.ContainerSlots)
                Else
                    Console.WriteLine("{0} Slot {1}", itItemTooltip.ContainerSlots, itItemTooltip.Subclass)
                End If
            End If

            If itItemTooltip.InventoryType <> Enums.InventoryType.NonEquipType Then
                Console.WriteLine([Enum].GetName(GetType(Enums.InventoryType), itItemTooltip.InventoryType))
            End If

            If itItemTooltip.ContainerSlots = 0 And Not String.IsNullOrEmpty(itItemTooltip.Subclass) Then
                Console.WriteLine(itItemTooltip.Subclass)
            End If

            If itItemTooltip.WeaponDamage.Count > 0 Then
                For Each ddData As DamageData In itItemTooltip.WeaponDamage
                    If ddData.DamageType = Enums.DamageTypeType.Physical Then
                        Console.WriteLine("{0}-{1} Dmg", ddData.Min, ddData.Max)
                    End If
                Next
            End If

            If itItemTooltip.WeaponSpeed > 0 Then
                Console.WriteLine("Speed {0:N2}", itItemTooltip.WeaponSpeed)
            End If

            If itItemTooltip.WeaponDPS > 0 Then
                Console.WriteLine("({0:N1} damage per second)", itItemTooltip.WeaponDPS)
            End If

            If itItemTooltip.StartQuestID > 0 Then
                Console.WriteLine("This Item Begins a Quest")
            End If

            If itItemTooltip.Conjured Then
                Console.WriteLine("Conjured")
            End If

            If Not String.IsNullOrEmpty(itItemTooltip.GlyphType) Then
                Dim tiInfo As TextInfo = New CultureInfo("en-us", False).TextInfo
                Console.WriteLine("{0} Glyph", tiInfo.ToTitleCase(itItemTooltip.GlyphType.ToUpperInvariant))
            End If

            If itItemTooltip.TotalArmor > 0 Then
                Console.WriteLine("{0} Armor", itItemTooltip.TotalArmor)
            End If

            If itItemTooltip.BlockValue > 0 Then
                Console.WriteLine("{0} Block", itItemTooltip.BlockValue)
            End If

            If itItemTooltip.BonusStrength > 0 Then
                Console.WriteLine("+{0} Strength", itItemTooltip.BonusStrength)
            End If

            If itItemTooltip.BonusAgility > 0 Then
                Console.WriteLine("+{0} Agility", itItemTooltip.BonusAgility)
            End If

            If itItemTooltip.BonusStamina > 0 Then
                Console.WriteLine("+{0} Stamina", itItemTooltip.BonusStamina)
            End If

            If itItemTooltip.BonusIntellect > 0 Then
                Console.WriteLine("+{0} Intellect", itItemTooltip.BonusIntellect)
            End If

            If itItemTooltip.BonusSpirit > 0 Then
                Console.WriteLine("+{0} Spirit", itItemTooltip.BonusSpirit)
            End If

            If itItemTooltip.FireResistance > 0 Then
                Console.WriteLine("+{0} Fire Resistance", itItemTooltip.FireResistance)
            End If

            If itItemTooltip.NatureResistance > 0 Then
                Console.WriteLine("+{0} Nature Resistance", itItemTooltip.NatureResistance)
            End If

            If itItemTooltip.FrostResistance > 0 Then
                Console.WriteLine("+{0} Frost Resistance", itItemTooltip.FrostResistance)
            End If

            If itItemTooltip.ShadowResistance > 0 Then
                Console.WriteLine("+{0} Shadow Resistance", itItemTooltip.ShadowResistance)
            End If

            If itItemTooltip.ArcaneResistance > 0 Then
                Console.WriteLine("+{0} Arcane Resistance", itItemTooltip.ArcaneResistance)
            End If

            If itItemTooltip.RandomEnchantments.Count > 0 Then
                For Each strEnchantment As String In itItemTooltip.RandomEnchantments
                    Console.WriteLine(strEnchantment)
                Next
            End If

            If Not String.IsNullOrEmpty(itItemTooltip.Enchantment) Then
                Console.WriteLine(itItemTooltip.Enchantment)
            End If

            If Not String.IsNullOrEmpty(itItemTooltip.GemProperties) Then
                Console.WriteLine(itItemTooltip.GemProperties)
            End If

            If itItemTooltip.Sockets.Count > 0 Then
                For Each sdSocket As SocketData In itItemTooltip.Sockets
                    If String.IsNullOrEmpty(sdSocket.Enchant) Then
                        Console.WriteLine("{0} Socket", sdSocket.Color)
                    Else
                        Console.WriteLine("{0} Socket: {1}", sdSocket.Color, sdSocket.Enchant)
                    End If
                Next
            End If

            If Not String.IsNullOrEmpty(itItemTooltip.SocketBonus) Then
                Console.WriteLine(itItemTooltip.SocketBonus)
            End If

            If itItemTooltip.Durability > 0 Then
                Console.WriteLine("Durability: {0}/{1}", itItemTooltip.CurrentDurability, itItemTooltip.Durability)
            End If

            If itItemTooltip.AllowableRaces.Count > 0 Then
                Console.WriteLine("Races: {0}", String.Join(", ", itItemTooltip.AllowableRaces.ToArray()))
            End If

            If itItemTooltip.AllowableClasses.Count > 0 Then
                Console.WriteLine("Classes: {0}", String.Join(", ", itItemTooltip.AllowableClasses.ToArray()))
            End If

            If itItemTooltip.RequiredLevel > 0 Then
                Console.WriteLine("Requires Level {0}", itItemTooltip.RequiredLevel)
            End If

            If itItemTooltip.RequiredLevelMin > 0 And itItemTooltip.RequiredLevelMax > 0 Then
                If itItemTooltip.RequiredLevelCur > 0 Then
                    Console.WriteLine("Requires Level {0} - {1} ({2})", itItemTooltip.RequiredLevelMin, itItemTooltip.RequiredLevelMax, itItemTooltip.RequiredLevelCur)
                Else
                    Console.WriteLine("Requires Level {0} - {1}", itItemTooltip.RequiredLevelMin, itItemTooltip.RequiredLevelMax)
                End If
            End If

            If Not String.IsNullOrEmpty(itItemTooltip.RequiredAbility) Then
                Console.WriteLine("Requires {0}", itItemTooltip.RequiredAbility)
            End If

            If Not String.IsNullOrEmpty(itItemTooltip.RequiredSkill) Then
                If itItemTooltip.RequiredSkillLevel = 0 Then
                    Console.WriteLine("Requires {0}", itItemTooltip.RequiredSkill)
                Else
                    Console.WriteLine("Requires {0} {1}", itItemTooltip.RequiredSkill, itItemTooltip.RequiredSkillLevel)
                End If
            End If

            If itItemTooltip.ItemLevel > 0 Then
                Console.WriteLine("Item Level {0}", itItemTooltip.ItemLevel)
            End If

            If itItemTooltip.RequiredPersonalArenaRating > 0 Then
                Console.WriteLine("Requires personal arena rating of {0}", itItemTooltip.RequiredPersonalArenaRating)
            End If

            If Not String.IsNullOrEmpty(itItemTooltip.RequiredFaction) Then
                If itItemTooltip.RequiredFactionStanding = Enums.FactionStandingType.None Then
                    Console.WriteLine("Requires {0}", itItemTooltip.RequiredFaction)
                Else
                    Console.WriteLine("Requires {0} - {1}", itItemTooltip.RequiredFaction, [Enum].GetName(GetType(Enums.FactionStandingType), itItemTooltip.RequiredFactionStanding))
                End If
            End If

            If itItemTooltip.BonusHitRating > 0 Then
                Console.WriteLine("Equip: Improves hit rating by {0}", itItemTooltip.BonusHitRating)
            End If

            If itItemTooltip.BonusCritRating > 0 Then
                Console.WriteLine("Equip: Improves critical strike rating by {0}", itItemTooltip.BonusCritRating)
            End If

            If itItemTooltip.BonusHasteRating > 0 Then
                Console.WriteLine("Equip: Improves haste rating by {0}", itItemTooltip.BonusHasteRating)
            End If

            If itItemTooltip.BonusAttackPower > 0 Then
                Console.WriteLine("Equip: Increases your attack power by {0}", itItemTooltip.BonusAttackPower)
            End If

            If itItemTooltip.BonusSpellPower > 0 Then
                Console.WriteLine("Equip: Increases spell power by {0}", itItemTooltip.BonusSpellPower)
            End If

            If itItemTooltip.BonusManaRegen > 0 Then
                Console.WriteLine("Equip: Restores {0} mana per 5 secs", itItemTooltip.BonusManaRegen)
            End If

            If itItemTooltip.BonusHealthRegen > 0 Then
                Console.WriteLine("Equip: Restores {0} health per 5 secs", itItemTooltip.BonusHealthRegen)
            End If

            If itItemTooltip.BonusDefenseSkillRating > 0 Then
                Console.WriteLine("Equip: Increases your defense rating by {0}", itItemTooltip.BonusDefenseSkillRating)
            End If

            If itItemTooltip.BonusDodgeRating > 0 Then
                Console.WriteLine("Equip: Increases your dodge rating by {0}", itItemTooltip.BonusDodgeRating)
            End If

            If itItemTooltip.BonusParryRating > 0 Then
                Console.WriteLine("Equip: Increases your parry rating by {0}", itItemTooltip.BonusParryRating)
            End If

            If itItemTooltip.BonusExpertiseRating > 0 Then
                Console.WriteLine("Equip: Increases your expertise rating by {0}", itItemTooltip.BonusExpertiseRating)
            End If

            If itItemTooltip.BonusArmorPenetrationRating > 0 Then
                Console.WriteLine("Equip: Increases your armor penetration rating by {0}", itItemTooltip.BonusArmorPenetrationRating)
            End If

            If itItemTooltip.BonusSpellPenetrationRating > 0 Then
                Console.WriteLine("Equip: Increases your spell penetration rating by {0}", itItemTooltip.BonusSpellPenetrationRating)
            End If

            If itItemTooltip.BonusResilienceRating > 0 Then
                Console.WriteLine("Equip: Increases your resilience rating by {0}", itItemTooltip.BonusResilienceRating)
            End If

            If itItemTooltip.BonusBlockRating > 0 Then
                Console.WriteLine("Equip: Increases your block rating by {0}", itItemTooltip.BonusBlockRating)
            End If

            If itItemTooltip.BonusBlockValue > 0 Then
                Console.WriteLine("Equip: Increases block value by {0}", itItemTooltip.BonusBlockValue)
            End If

            If itItemTooltip.Spells.Count > 0 Then
                For Each sdSpell As SpellData In itItemTooltip.Spells
                    If sdSpell.Charges = 0 Then
                        Console.WriteLine("{0}: {1}", [Enum].GetName(GetType(Enums.SpellTriggerType), sdSpell.Trigger), sdSpell.Description)
                    Else
                        Console.WriteLine("{0}: {1} ({2} charges)", [Enum].GetName(GetType(Enums.SpellTriggerType), sdSpell.Trigger), sdSpell.Description, sdSpell.Charges)
                    End If
                Next
            End If

            If itItemTooltip.Set IsNot Nothing Then
                Console.WriteLine()
                Console.WriteLine(itItemTooltip.Set.Name)
                For Each siItem As SetItem In itItemTooltip.Set.Items
                    Console.WriteLine("  {0}", siItem.Name)
                Next
                Console.WriteLine()
                For Each sbBonus As SetBonus In itItemTooltip.Set.SetBonuses
                    Console.WriteLine("({0}) Set: {1}", sbBonus.Threshold, sbBonus.Description)
                Next
            End If

            If Not String.IsNullOrEmpty(itItemTooltip.FlavorText) Then
                Console.WriteLine("""{0}""", itItemTooltip.FlavorText)
            End If

            Console.WriteLine()
            Console.WriteLine("Press any key to continue.")
            Console.ReadKey(True)
        End Sub

    End Module

End Namespace